--HG--
branch : minor
This commit is contained in:
Kyle McLamb
2017-08-02 19:33:42 -04:00
148 changed files with 3019 additions and 2467 deletions
+6 -10
View File
@@ -255,6 +255,7 @@ endfunction()
set(LOVE_SRC_COMMON set(LOVE_SRC_COMMON
src/common/b64.cpp src/common/b64.cpp
src/common/b64.h src/common/b64.h
src/common/Color.h
src/common/config.h src/common/config.h
src/common/Data.cpp src/common/Data.cpp
src/common/Data.h src/common/Data.h
@@ -474,7 +475,6 @@ set(LOVE_SRC_MODULE_GRAPHICS_ROOT
src/modules/graphics/Buffer.h src/modules/graphics/Buffer.h
src/modules/graphics/Canvas.cpp src/modules/graphics/Canvas.cpp
src/modules/graphics/Canvas.h src/modules/graphics/Canvas.h
src/modules/graphics/Color.h
src/modules/graphics/depthstencil.cpp src/modules/graphics/depthstencil.cpp
src/modules/graphics/depthstencil.h src/modules/graphics/depthstencil.h
src/modules/graphics/Drawable.cpp src/modules/graphics/Drawable.cpp
@@ -575,8 +575,13 @@ source_group("modules\\graphics\\opengl" FILES ${LOVE_SRC_MODULE_GRAPHICS_OPENGL
# #
set(LOVE_SRC_MODULE_IMAGE_ROOT set(LOVE_SRC_MODULE_IMAGE_ROOT
src/modules/image/CompressedFormatHandler.h
src/modules/image/CompressedImageData.cpp src/modules/image/CompressedImageData.cpp
src/modules/image/CompressedImageData.h src/modules/image/CompressedImageData.h
src/modules/image/CompressedSlice.cpp
src/modules/image/CompressedSlice.h
src/modules/image/FormatHandler.cpp
src/modules/image/FormatHandler.h
src/modules/image/Image.cpp src/modules/image/Image.cpp
src/modules/image/Image.h src/modules/image/Image.h
src/modules/image/ImageData.cpp src/modules/image/ImageData.cpp
@@ -594,19 +599,10 @@ set(LOVE_SRC_MODULE_IMAGE_ROOT
set(LOVE_SRC_MODULE_IMAGE_MAGPIE set(LOVE_SRC_MODULE_IMAGE_MAGPIE
src/modules/image/magpie/ASTCHandler.cpp src/modules/image/magpie/ASTCHandler.cpp
src/modules/image/magpie/ASTCHandler.h src/modules/image/magpie/ASTCHandler.h
src/modules/image/magpie/CompressedImageData.cpp
src/modules/image/magpie/CompressedImageData.h
src/modules/image/magpie/CompressedFormatHandler.h
src/modules/image/magpie/ddsHandler.cpp src/modules/image/magpie/ddsHandler.cpp
src/modules/image/magpie/ddsHandler.h src/modules/image/magpie/ddsHandler.h
src/modules/image/magpie/EXRHandler.cpp src/modules/image/magpie/EXRHandler.cpp
src/modules/image/magpie/EXRHandler.h src/modules/image/magpie/EXRHandler.h
src/modules/image/magpie/FormatHandler.cpp
src/modules/image/magpie/FormatHandler.h
src/modules/image/magpie/Image.cpp
src/modules/image/magpie/Image.h
src/modules/image/magpie/ImageData.cpp
src/modules/image/magpie/ImageData.h
src/modules/image/magpie/KTXHandler.cpp src/modules/image/magpie/KTXHandler.cpp
src/modules/image/magpie/KTXHandler.h src/modules/image/magpie/KTXHandler.h
src/modules/image/magpie/PKMHandler.cpp src/modules/image/magpie/PKMHandler.cpp
+40 -9
View File
@@ -3,54 +3,80 @@ LOVE 0.11.0 []
Released: N/A Released: N/A
* Added Object:release.
* Added Data:clone.
* Added queueable audio sources.
* Added audio input support.
* Added Source filters: low gain, high gain and band pass.
* Added audio effect APIs (reverb, echo, etc.)
* Added a variant to World:update, which accepts the number of iterations to run. The defaults are now 8 and 3. * Added a variant to World:update, which accepts the number of iterations to run. The defaults are now 8 and 3.
* Added a click count argument to love.mousepressed and love.mousereleased. * Added a click count argument to love.mousepressed and love.mousereleased.
* Added love.filesystem.get/setCRequirePath, and use that to find c libraries for require. * Added love.filesystem.get/setCRequirePath, and use that to find c libraries for require.
* Added Channel:hasRead, which checks if a message has been read. Takes an id, which Channel:push will now return. * Added Channel:hasRead, which checks if a message has been read. Takes an id, which Channel:push will now return.
* Added love.math.encode/decode, which support hex and base64. * Added love.math.encode/decode, which support hex and base64.
* Added love.math.hash, which supports MD5, SHA-1 and the SHA-2 family. * Added love.math.hash, which supports MD5, SHA-1 and the SHA-2 family.
* Added Transform objects to love.math.
* Added support for different ImageData formats, including RGBA8 (the default), RGBA16, RGBA16F, and RGBA32F. * Added support for different ImageData formats, including RGBA8 (the default), RGBA16, RGBA16F, and RGBA32F.
* Added the ability to load Radiance HDR, OpenEXR, and 16 bit PNG images. * Added the ability to load Radiance HDR, OpenEXR, and 16 bit PNG images.
* Added love.graphics.getImageFormats (replaces love.graphics.getCompressedImageFormats). * Added love.graphics.getImageFormats (replaces love.graphics.getCompressedImageFormats).
* Added the ability to specify a per-object pixel density scale factor when creating Images, Canvases, Fonts, and Videos. Affects drawing. * Added the ability to specify a per-object pixel density scale factor when creating Images, Canvases, Fonts, and Videos. Affects drawing.
* Added Texture:getPixelWidth/Height and love.graphics.getPixelWidth/Height. * Added Texture:getPixelWidth/Height and love.graphics.getPixelWidth/Height.
* Added Texture:getPixelDensity, love.graphics.getPixelDensity, and Font:getPixelDensity. * Added Texture:getPixelDensity, love.graphics.getPixelDensity, and Font:getPixelDensity.
* Added Array, Cubemap, and Volume texture types and corresponding Image and Canvas APIs.
* Added love.graphics.getTextureTypes, returns a table with fields indicating support for each texture type.
* Added mipmapping support to Canvases, including both auto-generated mipmaps and manually rendering to a specific mipmap level.
* Added 'stencil8', 'depth24stencil8', 'depth32fstencil8', 'depth16', 'depth24', and 'depth32f' pixel formats for Canvases.
* Added optional 'readable' boolean field to the table passed into love.graphics.newCanvas.
* Added optional 'depthstencil' field to the table passed into love.graphics.setCanvas, for using a depth/stencil Canvas.
* Added optional 'depth' and 'stencil' boolean fields to the table passed into setCanvas, for enabling depth and stencil buffers if 'depthstencil' isn't used.
* Added shadow sampler support for Canvases.
* Added variant of love.graphics.getCanvasFormats which takes a 'readable' boolean.
* Added love.graphics.drawLayer and SpriteBatch:add/setLayer for easily drawing layers of Array Textures.
* Added variants of love.graphics.print and printf which take a Font argument.
* Added variants of love.graphics.clear to control how the active depth and stencil buffers are cleared.
* Added love.graphics.flushBatch for manually flushing automatically batched draws.
* Added SpriteBatch:setDrawRange. * Added SpriteBatch:setDrawRange.
* Added per-shader opt in support for the GLSL 3.30 and GLSL ES 3.00 shading languages. * Added per-shader opt in support for the GLSL 3.30 and GLSL ES 3.00 shading languages.
* Added 'void effect()' pixel shader entry point.
* Added love.graphics.validateShader. * Added love.graphics.validateShader.
* Added Shader:hasUniform. * Added Shader:hasUniform.
* Added support for non-square shader uniform matrices on desktop platforms and on mobile GLSL 3. * Added support for non-square shader uniform matrices on desktop platforms and on mobile GLSL 3.
* Added Shader:send(matrixname, is_column_major, matrix, ...) which specifies how to interpret the matrix table arguments. * Added Shader:send(matrixname, is_column_major, matrix, ...) which specifies how to interpret the matrix table arguments.
* Added 'borderellipse' and 'borderrectangle' ParticleSystem distributions.
* Added ParticleSystem:set/getAreaSpreadAngle and set/getAreaSpreadIsRelativeDirection.
* Added love.graphics.captureScreenshot (replaces love.graphics.newScreenshot). * Added love.graphics.captureScreenshot (replaces love.graphics.newScreenshot).
* Added love.window.updateMode. * Added 'glsl3', 'instancing', 'fullnpot','pixelshaderhighp', and 'shaderderivatives' graphics features.
* Added the ability to prevent love from creating a stencil buffer for the window.
* Added Object:release.
* Added queueable audio sources.
* Added audio input support.
* Added Transform objects to love.math.
* Added 'glsl3', 'instancing', 'fullnpot', and 'pixelshaderhighp' graphics features.
* Added 'anisotropy' graphics limit. * Added 'anisotropy' graphics limit.
* Added Mesh instancing support. * Added Mesh instancing support via love.graphics.drawInstanced and Mesh:attachAttribute.
* Added a Mesh:attachAttribute variant that takes a different target attribute name. * Added a Mesh:attachAttribute variant that takes a different target attribute name.
* Added Mesh:detachAttribute. * Added Mesh:detachAttribute.
* Added a variant of Mesh:setVertexMap which accepts a Data object. * Added a variant of Mesh:setVertexMap which accepts a Data object.
* Added Source filters: low gain, high gain and band pass. * Added love.window.updateMode.
* Added the ability to prevent love from creating a stencil buffer for the window.
* Changed all color values to be in the range 0-1, rather than 0-255. * Changed all color values to be in the range 0-1, rather than 0-255.
* Changed high-dpi functionality to require much less code (often none at all) for things to appear at the correct sizes and positions. * Changed high-dpi functionality to require much less code (often none at all) for things to appear at the correct sizes and positions.
* Changed love.graphics.print and friends to ignore carriage returns. * Changed love.graphics.print and friends to ignore carriage returns.
* Changed the 'multiply' blend mode to error if not used with the 'premultiplied' blend alpha mode, since the formula only works with that anyway. * Changed the 'multiply' blend mode to error if not used with the 'premultiplied' blend alpha mode, since the formula only works with that anyway.
* Changed some love.graphics, love.window, and love.event APIs to cause an error if a Canvas is active. * Changed some love.graphics, love.window, and love.event APIs to cause an error if a Canvas is active.
* Changed stenciling functionality with a Canvas active to require stencil=true (or a custom stencil-formatted Canvas) to be set in setCanvas.
* Changed Mesh:setDrawRange to take 'start' and 'count' parameters instead of 'min' and 'max'. * Changed Mesh:setDrawRange to take 'start' and 'count' parameters instead of 'min' and 'max'.
* Changed the 'vsync' field of love.window.setMode and t.window in love.conf. It's now an integer with 0 disabling vsync. * Changed the 'vsync' field of love.window.setMode and t.window in love.conf. It's now an integer with 0 disabling vsync.
* Changed the audio playback APIs drastically. * Changed the audio playback APIs drastically.
* Changed enet to no longer set the 'enet' global, again matching luasocket. * Changed enet to no longer set the 'enet' global, again matching luasocket.
* Changed Source seeking behaviour, all kinds of Sources now behave similarly when seeking past the boundaries. * Changed Source seeking behaviour, all kinds of Sources now behave similarly when seeking past the boundaries.
* Fixed a memory leak when sending love objects to threads which never load that object's module.
* Fixed os.execute always returning -1 in Linux.
* Fixed the default reference angle for WeldJoint, PrismaticJoint, and RevoluteJoint.
* Fixed love.graphics.set/getClipboard text to error instead of crashing, when a window hasn't been created.
* Fixed Joystick:getGamepadMapping to work with xinput controllers. * Fixed Joystick:getGamepadMapping to work with xinput controllers.
* Fixed baseline calculation when rendering text.
* Fixed VaryingTexCoords and love_ScreenSize in shaders to be 'highp' in OpenGL ES, when supported.
* Improved performance when drawing textures, shapes, lines, and points by automatically batching their draw calls together when possible. * Improved performance when drawing textures, shapes, lines, and points by automatically batching their draw calls together when possible.
* Improved performance of Shader:send when the Shader is not active. * Improved performance of Shader:send when the Shader is not active.
* Improved performance of love.math.randomNormal when LuaJIT's JIT compiler is enabled.
* Renamed love.window.getPixelScale to love.window.getPixelDensity. * Renamed love.window.getPixelScale to love.window.getPixelDensity.
@@ -58,6 +84,7 @@ Released: N/A
* Removed variant of love.filesystem.newFileData which takes base64 data, use love.math.decode instead. * Removed variant of love.filesystem.newFileData which takes base64 data, use love.math.decode instead.
* Removed the no-argument variant of Text:set, use Text:clear instead. * Removed the no-argument variant of Text:set, use Text:clear instead.
* Removed love.graphics.getCompressedImageFormats, use love.graphics.getImageFormats instead. * Removed love.graphics.getCompressedImageFormats, use love.graphics.getImageFormats instead.
* Removed the 'void effects(...)' pixel shader entry point. Use the new 'void effect()' instead.
* Removed Shader:getExternVariable, use Shader:hasUniform instead. * Removed Shader:getExternVariable, use Shader:hasUniform instead.
* Removed love.graphics.newScreenshot, use love.graphics.captureScreenshot instead. * Removed love.graphics.newScreenshot, use love.graphics.captureScreenshot instead.
* Removed deprecated enet function host:socket_get_address. * Removed deprecated enet function host:socket_get_address.
@@ -66,9 +93,12 @@ Released: N/A
* Removed love.window.isCreated (use love.window.isOpen instead). * Removed love.window.isCreated (use love.window.isOpen instead).
* Updated Source:seek to work if the Source isn't playing. * Updated Source:seek to work if the Source isn't playing.
* Updated love.event.poll to stop allocating memory unnecessarily.
* Updated love.math.random to have improved numeric distribution. * Updated love.math.random to have improved numeric distribution.
* Updated love.graphics to support Core Profile OpenGL 3.3+ when available. * Updated love.graphics to support Core Profile OpenGL 3.3+ when available.
* Updated shaders to always expose derivative functions (dFdx, dFdy, fwidth) when available in OpenGL ES.
* Updated love.graphics.circle/ellipse/arc/rectangle to take transformation scale into account when determining the number of segments to use. * Updated love.graphics.circle/ellipse/arc/rectangle to take transformation scale into account when determining the number of segments to use.
* Updated Font glyph generation to improve antialiasing.
* Updated Canvas:newImageData to return an ImageData with a format that matches the Canvas' as closely as possible. * Updated Canvas:newImageData to return an ImageData with a format that matches the Canvas' as closely as possible.
* Updated love.graphics.newImage to treat file names ending with "@2x", "@3x", etc. as a pixel density scale factor if none is explicitly supplied. * Updated love.graphics.newImage to treat file names ending with "@2x", "@3x", etc. as a pixel density scale factor if none is explicitly supplied.
* Updated luasocket to version 3.0rc1. * Updated luasocket to version 3.0rc1.
@@ -83,6 +113,7 @@ Released: N/A
* Fixed Shader:send and Shader:sendColor ignoring the last argument for an array. * Fixed Shader:send and Shader:sendColor ignoring the last argument for an array.
* Fixed a crash when love.graphics.pop is called after a love.window.setMode while the transformation stack was not empty. * Fixed a crash when love.graphics.pop is called after a love.window.setMode while the transformation stack was not empty.
* Fixed BezierCurves to error instead of hanging in some situations. * Fixed BezierCurves to error instead of hanging in some situations.
* Fixed compilation of luasocket with newer luajit 2.1.0 beta versions.
* Improved command line argument handling. * Improved command line argument handling.
* Improved seeking support, especially for short video files. * Improved seeking support, especially for short video files.
+149 -73
View File
@@ -23,9 +23,9 @@ distribution.
--------- ---------
This software uses LuaJIT: This software uses ENet:
LuaJIT is Copyright (c) 2005-2016 Mike Pall Copyright (c) 2002-2016 Lee Salzman
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@@ -47,6 +47,31 @@ THE SOFTWARE.
--------- ---------
This software uses GLAD:
The MIT License (MIT)
Copyright (c) 2013 David Herberth, modified by Alex Szpakowski
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
---------
This software uses glslang: This software uses glslang:
Copyright (C) 2002-2005 3Dlabs Inc. Ltd. Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
@@ -85,30 +110,6 @@ POSSIBILITY OF SUCH DAMAGE.
--------- ---------
This software uses ENet:
Copyright (c) 2002-2016 Lee Salzman
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------
This software uses lua-enet: This software uses lua-enet:
Copyright (C) 2011 by Leaf Corcoran Copyright (C) 2011 by Leaf Corcoran
@@ -133,30 +134,76 @@ THE SOFTWARE.
--------- ---------
This software uses UTF8-CPP: This software uses LuaJIT:
Copyright 2006 Nemanja Trifunovic LuaJIT is Copyright (c) 2005-2016 Mike Pall
Permission is hereby granted, free of charge, to any person or organization Permission is hereby granted, free of charge, to any person obtaining a copy
obtaining a copy of the software and accompanying documentation covered by of this software and associated documentation files (the "Software"), to deal
this license (the "Software") to use, reproduce, display, distribute, in the Software without restriction, including without limitation the rights
execute, and transmit the Software, and to prepare derivative works of the to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
Software, and to permit third-parties to whom the Software is furnished to copies of the Software, and to permit persons to whom the Software is
do so, all subject to the following: furnished to do so, subject to the following conditions:
The copyright notices in the Software and this entire statement, including The above copyright notice and this permission notice shall be included in
the above license grant, this restriction and the following disclaimer, all copies or substantial portions of the Software.
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------
This software uses Lua's UTF-8 module:
Copyright (C) 1994-2015 Lua.org, PUC-Rio, 2015 LOVE Development Team.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
---------
This software uses luasocket:
LuaSocket 3.0 license
Copyright (C) 2004-2013 Diego Nehab
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
--------- ---------
@@ -197,6 +244,63 @@ You can contact the author at :
--------- ---------
This software uses TinyEXR:
Copyright (c) 2014 - 2016, Syoyo Fujita
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------
This software uses UTF8-CPP:
Copyright 2006 Nemanja Trifunovic
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
---------
This software uses xxHash: This software uses xxHash:
xxHash - Extremely Fast Hash algorithm xxHash - Extremely Fast Hash algorithm
@@ -232,41 +336,13 @@ You can contact the author at :
--------- ---------
This software uses TinyEXR:
Copyright (c) 2014 - 2016, Syoyo Fujita
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------
This software uses the following LGPL libraries on Windows, Mac OS X, Linux, This software uses the following LGPL libraries on Windows, Mac OS X, Linux,
and Android: and Android:
- libmpg123 - libmpg123
Website: http://www.mpg123.de/ Website: http://www.mpg123.de/
Source download: http://sourceforge.net/projects/mpg123/files/latest/download Source download: http://sourceforge.net/projects/mpg123/files/latest/download
- OpenAL Soft - OpenAL Soft
Website: http://kcat.strangesoft.net/openal.html Website: http://kcat.strangesoft.net/openal.html
Source download: http://kcat.strangesoft.net/openal.html#download Source download: http://kcat.strangesoft.net/openal.html#download
@@ -415,7 +415,6 @@
FA0B7D2B1A95902C000E1D17 /* wrap_Rasterizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7B851A95902C000E1D17 /* wrap_Rasterizer.cpp */; }; FA0B7D2B1A95902C000E1D17 /* wrap_Rasterizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7B851A95902C000E1D17 /* wrap_Rasterizer.cpp */; };
FA0B7D2C1A95902C000E1D17 /* wrap_Rasterizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7B851A95902C000E1D17 /* wrap_Rasterizer.cpp */; }; FA0B7D2C1A95902C000E1D17 /* wrap_Rasterizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7B851A95902C000E1D17 /* wrap_Rasterizer.cpp */; };
FA0B7D2D1A95902C000E1D17 /* wrap_Rasterizer.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7B861A95902C000E1D17 /* wrap_Rasterizer.h */; }; FA0B7D2D1A95902C000E1D17 /* wrap_Rasterizer.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7B861A95902C000E1D17 /* wrap_Rasterizer.h */; };
FA0B7D2E1A95902C000E1D17 /* Color.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7B881A95902C000E1D17 /* Color.h */; };
FA0B7D2F1A95902C000E1D17 /* Drawable.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7B891A95902C000E1D17 /* Drawable.h */; }; FA0B7D2F1A95902C000E1D17 /* Drawable.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7B891A95902C000E1D17 /* Drawable.h */; };
FA0B7D301A95902C000E1D17 /* Graphics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7B8A1A95902C000E1D17 /* Graphics.cpp */; }; FA0B7D301A95902C000E1D17 /* Graphics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7B8A1A95902C000E1D17 /* Graphics.cpp */; };
FA0B7D311A95902C000E1D17 /* Graphics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7B8A1A95902C000E1D17 /* Graphics.cpp */; }; FA0B7D311A95902C000E1D17 /* Graphics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7B8A1A95902C000E1D17 /* Graphics.cpp */; };
@@ -469,22 +468,9 @@
FA0B7D861A95902C000E1D17 /* ImageData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BC61A95902C000E1D17 /* ImageData.cpp */; }; FA0B7D861A95902C000E1D17 /* ImageData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BC61A95902C000E1D17 /* ImageData.cpp */; };
FA0B7D871A95902C000E1D17 /* ImageData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BC61A95902C000E1D17 /* ImageData.cpp */; }; FA0B7D871A95902C000E1D17 /* ImageData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BC61A95902C000E1D17 /* ImageData.cpp */; };
FA0B7D881A95902C000E1D17 /* ImageData.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7BC71A95902C000E1D17 /* ImageData.h */; }; FA0B7D881A95902C000E1D17 /* ImageData.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7BC71A95902C000E1D17 /* ImageData.h */; };
FA0B7D891A95902C000E1D17 /* CompressedImageData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BC91A95902C000E1D17 /* CompressedImageData.cpp */; };
FA0B7D8A1A95902C000E1D17 /* CompressedImageData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BC91A95902C000E1D17 /* CompressedImageData.cpp */; };
FA0B7D8B1A95902C000E1D17 /* CompressedImageData.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7BCA1A95902C000E1D17 /* CompressedImageData.h */; };
FA0B7D8C1A95902C000E1D17 /* CompressedFormatHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7BCB1A95902C000E1D17 /* CompressedFormatHandler.h */; };
FA0B7D8D1A95902C000E1D17 /* ddsHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BCC1A95902C000E1D17 /* ddsHandler.cpp */; }; FA0B7D8D1A95902C000E1D17 /* ddsHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BCC1A95902C000E1D17 /* ddsHandler.cpp */; };
FA0B7D8E1A95902C000E1D17 /* ddsHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BCC1A95902C000E1D17 /* ddsHandler.cpp */; }; FA0B7D8E1A95902C000E1D17 /* ddsHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BCC1A95902C000E1D17 /* ddsHandler.cpp */; };
FA0B7D8F1A95902C000E1D17 /* ddsHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7BCD1A95902C000E1D17 /* ddsHandler.h */; }; FA0B7D8F1A95902C000E1D17 /* ddsHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7BCD1A95902C000E1D17 /* ddsHandler.h */; };
FA0B7D901A95902C000E1D17 /* FormatHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BCE1A95902C000E1D17 /* FormatHandler.cpp */; };
FA0B7D911A95902C000E1D17 /* FormatHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BCE1A95902C000E1D17 /* FormatHandler.cpp */; };
FA0B7D921A95902C000E1D17 /* FormatHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7BCF1A95902C000E1D17 /* FormatHandler.h */; };
FA0B7D931A95902C000E1D17 /* Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BD01A95902C000E1D17 /* Image.cpp */; };
FA0B7D941A95902C000E1D17 /* Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BD01A95902C000E1D17 /* Image.cpp */; };
FA0B7D951A95902C000E1D17 /* Image.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7BD11A95902C000E1D17 /* Image.h */; };
FA0B7D961A95902C000E1D17 /* ImageData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BD21A95902C000E1D17 /* ImageData.cpp */; };
FA0B7D971A95902C000E1D17 /* ImageData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BD21A95902C000E1D17 /* ImageData.cpp */; };
FA0B7D981A95902C000E1D17 /* ImageData.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7BD31A95902C000E1D17 /* ImageData.h */; };
FA0B7D9F1A95902C000E1D17 /* KTXHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BD81A95902C000E1D17 /* KTXHandler.cpp */; }; FA0B7D9F1A95902C000E1D17 /* KTXHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BD81A95902C000E1D17 /* KTXHandler.cpp */; };
FA0B7DA01A95902C000E1D17 /* KTXHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BD81A95902C000E1D17 /* KTXHandler.cpp */; }; FA0B7DA01A95902C000E1D17 /* KTXHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7BD81A95902C000E1D17 /* KTXHandler.cpp */; };
FA0B7DA11A95902C000E1D17 /* KTXHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7BD91A95902C000E1D17 /* KTXHandler.h */; }; FA0B7DA11A95902C000E1D17 /* KTXHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7BD91A95902C000E1D17 /* KTXHandler.h */; };
@@ -938,6 +924,7 @@
FA620A371AA2F8DB005DB4C2 /* wrap_Texture.h in Headers */ = {isa = PBXBuildFile; fileRef = FA620A311AA2F8DB005DB4C2 /* wrap_Texture.h */; }; FA620A371AA2F8DB005DB4C2 /* wrap_Texture.h in Headers */ = {isa = PBXBuildFile; fileRef = FA620A311AA2F8DB005DB4C2 /* wrap_Texture.h */; };
FA620A3A1AA305F6005DB4C2 /* types.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA620A391AA305F6005DB4C2 /* types.cpp */; }; FA620A3A1AA305F6005DB4C2 /* types.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA620A391AA305F6005DB4C2 /* types.cpp */; };
FA620A3B1AA305F6005DB4C2 /* types.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA620A391AA305F6005DB4C2 /* types.cpp */; }; FA620A3B1AA305F6005DB4C2 /* types.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA620A391AA305F6005DB4C2 /* types.cpp */; };
FA6BDE5C1F31725300786805 /* Color.h in Headers */ = {isa = PBXBuildFile; fileRef = FA6BDE5B1F31725300786805 /* Color.h */; };
FA7550A81AEBE276003E311E /* libluajit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FA7550A71AEBE276003E311E /* libluajit.a */; }; FA7550A81AEBE276003E311E /* libluajit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FA7550A71AEBE276003E311E /* libluajit.a */; };
FA76344A1E28722A0066EF9E /* StreamBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA7634481E28722A0066EF9E /* StreamBuffer.cpp */; }; FA76344A1E28722A0066EF9E /* StreamBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA7634481E28722A0066EF9E /* StreamBuffer.cpp */; };
FA76344B1E28722A0066EF9E /* StreamBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA7634481E28722A0066EF9E /* StreamBuffer.cpp */; }; FA76344B1E28722A0066EF9E /* StreamBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA7634481E28722A0066EF9E /* StreamBuffer.cpp */; };
@@ -948,6 +935,9 @@
FA91591E1CF1ED7500A7053F /* halffloat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA91591C1CF1ED7500A7053F /* halffloat.cpp */; }; FA91591E1CF1ED7500A7053F /* halffloat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA91591C1CF1ED7500A7053F /* halffloat.cpp */; };
FA91591F1CF1ED7500A7053F /* halffloat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA91591C1CF1ED7500A7053F /* halffloat.cpp */; }; FA91591F1CF1ED7500A7053F /* halffloat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA91591C1CF1ED7500A7053F /* halffloat.cpp */; };
FA9159201CF1ED7500A7053F /* halffloat.h in Headers */ = {isa = PBXBuildFile; fileRef = FA91591D1CF1ED7500A7053F /* halffloat.h */; }; FA9159201CF1ED7500A7053F /* halffloat.h in Headers */ = {isa = PBXBuildFile; fileRef = FA91591D1CF1ED7500A7053F /* halffloat.h */; };
FA93C4521F315B960087CCD4 /* CompressedFormatHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = FA93C44F1F315B960087CCD4 /* CompressedFormatHandler.h */; };
FA93C4531F315B960087CCD4 /* FormatHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = FA93C4501F315B960087CCD4 /* FormatHandler.h */; };
FA93C4541F315B960087CCD4 /* FormatHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA93C4511F315B960087CCD4 /* FormatHandler.cpp */; };
FA9B4A0816E1578300074F42 /* SDL2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA9B4A0716E1578300074F42 /* SDL2.framework */; }; FA9B4A0816E1578300074F42 /* SDL2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA9B4A0716E1578300074F42 /* SDL2.framework */; };
FA9D8DD11DEB56C3002CD881 /* pixelformat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA9D8DCF1DEB56C3002CD881 /* pixelformat.cpp */; }; FA9D8DD11DEB56C3002CD881 /* pixelformat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA9D8DCF1DEB56C3002CD881 /* pixelformat.cpp */; };
FA9D8DD21DEB56C3002CD881 /* pixelformat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA9D8DCF1DEB56C3002CD881 /* pixelformat.cpp */; }; FA9D8DD21DEB56C3002CD881 /* pixelformat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA9D8DCF1DEB56C3002CD881 /* pixelformat.cpp */; };
@@ -1036,6 +1026,10 @@
FADF543D1E3DAFF700012CC0 /* wrap_Graphics.h in Headers */ = {isa = PBXBuildFile; fileRef = FADF543A1E3DAFF700012CC0 /* wrap_Graphics.h */; }; FADF543D1E3DAFF700012CC0 /* wrap_Graphics.h in Headers */ = {isa = PBXBuildFile; fileRef = FADF543A1E3DAFF700012CC0 /* wrap_Graphics.h */; };
FAE272521C05A15B00A67640 /* ParticleSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAE272501C05A15B00A67640 /* ParticleSystem.cpp */; }; FAE272521C05A15B00A67640 /* ParticleSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAE272501C05A15B00A67640 /* ParticleSystem.cpp */; };
FAE272531C05A15B00A67640 /* ParticleSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = FAE272511C05A15B00A67640 /* ParticleSystem.h */; }; FAE272531C05A15B00A67640 /* ParticleSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = FAE272511C05A15B00A67640 /* ParticleSystem.h */; };
FAECA1B21F3164700095D008 /* CompressedSlice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAECA1B01F3164700095D008 /* CompressedSlice.cpp */; };
FAECA1B31F3164700095D008 /* CompressedSlice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAECA1B01F3164700095D008 /* CompressedSlice.cpp */; };
FAECA1B41F3164700095D008 /* CompressedSlice.h in Headers */ = {isa = PBXBuildFile; fileRef = FAECA1B11F3164700095D008 /* CompressedSlice.h */; };
FAECA1B51F31648A0095D008 /* FormatHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA93C4511F315B960087CCD4 /* FormatHandler.cpp */; };
FAF140531E20934C00F898D2 /* CodeGen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAF13FC21E20934C00F898D2 /* CodeGen.cpp */; }; FAF140531E20934C00F898D2 /* CodeGen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAF13FC21E20934C00F898D2 /* CodeGen.cpp */; };
FAF140541E20934C00F898D2 /* CodeGen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAF13FC21E20934C00F898D2 /* CodeGen.cpp */; }; FAF140541E20934C00F898D2 /* CodeGen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAF13FC21E20934C00F898D2 /* CodeGen.cpp */; };
FAF140551E20934C00F898D2 /* Link.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAF13FC31E20934C00F898D2 /* Link.cpp */; }; FAF140551E20934C00F898D2 /* Link.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAF13FC31E20934C00F898D2 /* Link.cpp */; };
@@ -1445,7 +1439,6 @@
FA0B7B841A95902C000E1D17 /* wrap_GlyphData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_GlyphData.h; sourceTree = "<group>"; }; FA0B7B841A95902C000E1D17 /* wrap_GlyphData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_GlyphData.h; sourceTree = "<group>"; };
FA0B7B851A95902C000E1D17 /* wrap_Rasterizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Rasterizer.cpp; sourceTree = "<group>"; }; FA0B7B851A95902C000E1D17 /* wrap_Rasterizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Rasterizer.cpp; sourceTree = "<group>"; };
FA0B7B861A95902C000E1D17 /* wrap_Rasterizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Rasterizer.h; sourceTree = "<group>"; }; FA0B7B861A95902C000E1D17 /* wrap_Rasterizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Rasterizer.h; sourceTree = "<group>"; };
FA0B7B881A95902C000E1D17 /* Color.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Color.h; sourceTree = "<group>"; };
FA0B7B891A95902C000E1D17 /* Drawable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Drawable.h; sourceTree = "<group>"; }; FA0B7B891A95902C000E1D17 /* Drawable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Drawable.h; sourceTree = "<group>"; };
FA0B7B8A1A95902C000E1D17 /* Graphics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = Graphics.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; FA0B7B8A1A95902C000E1D17 /* Graphics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = Graphics.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
FA0B7B8B1A95902C000E1D17 /* Graphics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Graphics.h; sourceTree = "<group>"; }; FA0B7B8B1A95902C000E1D17 /* Graphics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Graphics.h; sourceTree = "<group>"; };
@@ -1482,17 +1475,8 @@
FA0B7BC51A95902C000E1D17 /* Image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Image.h; sourceTree = "<group>"; }; FA0B7BC51A95902C000E1D17 /* Image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Image.h; sourceTree = "<group>"; };
FA0B7BC61A95902C000E1D17 /* ImageData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageData.cpp; sourceTree = "<group>"; }; FA0B7BC61A95902C000E1D17 /* ImageData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageData.cpp; sourceTree = "<group>"; };
FA0B7BC71A95902C000E1D17 /* ImageData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageData.h; sourceTree = "<group>"; }; FA0B7BC71A95902C000E1D17 /* ImageData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageData.h; sourceTree = "<group>"; };
FA0B7BC91A95902C000E1D17 /* CompressedImageData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CompressedImageData.cpp; sourceTree = "<group>"; };
FA0B7BCA1A95902C000E1D17 /* CompressedImageData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompressedImageData.h; sourceTree = "<group>"; };
FA0B7BCB1A95902C000E1D17 /* CompressedFormatHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompressedFormatHandler.h; sourceTree = "<group>"; };
FA0B7BCC1A95902C000E1D17 /* ddsHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ddsHandler.cpp; sourceTree = "<group>"; }; FA0B7BCC1A95902C000E1D17 /* ddsHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ddsHandler.cpp; sourceTree = "<group>"; };
FA0B7BCD1A95902C000E1D17 /* ddsHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ddsHandler.h; sourceTree = "<group>"; }; FA0B7BCD1A95902C000E1D17 /* ddsHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ddsHandler.h; sourceTree = "<group>"; };
FA0B7BCE1A95902C000E1D17 /* FormatHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FormatHandler.cpp; sourceTree = "<group>"; };
FA0B7BCF1A95902C000E1D17 /* FormatHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FormatHandler.h; sourceTree = "<group>"; };
FA0B7BD01A95902C000E1D17 /* Image.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Image.cpp; sourceTree = "<group>"; };
FA0B7BD11A95902C000E1D17 /* Image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Image.h; sourceTree = "<group>"; };
FA0B7BD21A95902C000E1D17 /* ImageData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageData.cpp; sourceTree = "<group>"; };
FA0B7BD31A95902C000E1D17 /* ImageData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageData.h; sourceTree = "<group>"; };
FA0B7BD81A95902C000E1D17 /* KTXHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KTXHandler.cpp; sourceTree = "<group>"; }; FA0B7BD81A95902C000E1D17 /* KTXHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KTXHandler.cpp; sourceTree = "<group>"; };
FA0B7BD91A95902C000E1D17 /* KTXHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KTXHandler.h; sourceTree = "<group>"; }; FA0B7BD91A95902C000E1D17 /* KTXHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KTXHandler.h; sourceTree = "<group>"; };
FA0B7BDA1A95902C000E1D17 /* PKMHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PKMHandler.cpp; sourceTree = "<group>"; }; FA0B7BDA1A95902C000E1D17 /* PKMHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PKMHandler.cpp; sourceTree = "<group>"; };
@@ -1800,6 +1784,7 @@
FA620A301AA2F8DB005DB4C2 /* wrap_Texture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Texture.cpp; sourceTree = "<group>"; }; FA620A301AA2F8DB005DB4C2 /* wrap_Texture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Texture.cpp; sourceTree = "<group>"; };
FA620A311AA2F8DB005DB4C2 /* wrap_Texture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Texture.h; sourceTree = "<group>"; }; FA620A311AA2F8DB005DB4C2 /* wrap_Texture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Texture.h; sourceTree = "<group>"; };
FA620A391AA305F6005DB4C2 /* types.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = types.cpp; sourceTree = "<group>"; }; FA620A391AA305F6005DB4C2 /* types.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = types.cpp; sourceTree = "<group>"; };
FA6BDE5B1F31725300786805 /* Color.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Color.h; sourceTree = "<group>"; };
FA7550A71AEBE276003E311E /* libluajit.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libluajit.a; sourceTree = "<group>"; }; FA7550A71AEBE276003E311E /* libluajit.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libluajit.a; sourceTree = "<group>"; };
FA7634481E28722A0066EF9E /* StreamBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StreamBuffer.cpp; sourceTree = "<group>"; }; FA7634481E28722A0066EF9E /* StreamBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StreamBuffer.cpp; sourceTree = "<group>"; };
FA7634491E28722A0066EF9E /* StreamBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StreamBuffer.h; sourceTree = "<group>"; }; FA7634491E28722A0066EF9E /* StreamBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StreamBuffer.h; sourceTree = "<group>"; };
@@ -1808,6 +1793,9 @@
FA8951A11AA2EDF300EC385A /* wrap_Event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Event.h; sourceTree = "<group>"; }; FA8951A11AA2EDF300EC385A /* wrap_Event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Event.h; sourceTree = "<group>"; };
FA91591C1CF1ED7500A7053F /* halffloat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = halffloat.cpp; sourceTree = "<group>"; }; FA91591C1CF1ED7500A7053F /* halffloat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = halffloat.cpp; sourceTree = "<group>"; };
FA91591D1CF1ED7500A7053F /* halffloat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = halffloat.h; sourceTree = "<group>"; }; FA91591D1CF1ED7500A7053F /* halffloat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = halffloat.h; sourceTree = "<group>"; };
FA93C44F1F315B960087CCD4 /* CompressedFormatHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompressedFormatHandler.h; sourceTree = "<group>"; };
FA93C4501F315B960087CCD4 /* FormatHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FormatHandler.h; sourceTree = "<group>"; };
FA93C4511F315B960087CCD4 /* FormatHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FormatHandler.cpp; sourceTree = "<group>"; };
FA9B4A0716E1578300074F42 /* SDL2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL2.framework; path = /Library/Frameworks/SDL2.framework; sourceTree = "<absolute>"; }; FA9B4A0716E1578300074F42 /* SDL2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL2.framework; path = /Library/Frameworks/SDL2.framework; sourceTree = "<absolute>"; };
FA9D8DCF1DEB56C3002CD881 /* pixelformat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pixelformat.cpp; sourceTree = "<group>"; }; FA9D8DCF1DEB56C3002CD881 /* pixelformat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pixelformat.cpp; sourceTree = "<group>"; };
FA9D8DD01DEB56C3002CD881 /* pixelformat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pixelformat.h; sourceTree = "<group>"; }; FA9D8DD01DEB56C3002CD881 /* pixelformat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pixelformat.h; sourceTree = "<group>"; };
@@ -1870,6 +1858,8 @@
FADF543A1E3DAFF700012CC0 /* wrap_Graphics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Graphics.h; sourceTree = "<group>"; }; FADF543A1E3DAFF700012CC0 /* wrap_Graphics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Graphics.h; sourceTree = "<group>"; };
FAE272501C05A15B00A67640 /* ParticleSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParticleSystem.cpp; sourceTree = "<group>"; }; FAE272501C05A15B00A67640 /* ParticleSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParticleSystem.cpp; sourceTree = "<group>"; };
FAE272511C05A15B00A67640 /* ParticleSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParticleSystem.h; sourceTree = "<group>"; }; FAE272511C05A15B00A67640 /* ParticleSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParticleSystem.h; sourceTree = "<group>"; };
FAECA1B01F3164700095D008 /* CompressedSlice.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CompressedSlice.cpp; sourceTree = "<group>"; };
FAECA1B11F3164700095D008 /* CompressedSlice.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CompressedSlice.h; sourceTree = "<group>"; };
FAF13FC21E20934C00F898D2 /* CodeGen.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeGen.cpp; sourceTree = "<group>"; }; FAF13FC21E20934C00F898D2 /* CodeGen.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeGen.cpp; sourceTree = "<group>"; };
FAF13FC31E20934C00F898D2 /* Link.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Link.cpp; sourceTree = "<group>"; }; FAF13FC31E20934C00F898D2 /* Link.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Link.cpp; sourceTree = "<group>"; };
FAF13FC51E20934C00F898D2 /* arrays.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = arrays.h; sourceTree = "<group>"; }; FAF13FC51E20934C00F898D2 /* arrays.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = arrays.h; sourceTree = "<group>"; };
@@ -2029,6 +2019,7 @@
FAA3A9AD1B7D465A00CED060 /* android.h */, FAA3A9AD1B7D465A00CED060 /* android.h */,
FA0B78F71A958E3B000E1D17 /* b64.cpp */, FA0B78F71A958E3B000E1D17 /* b64.cpp */,
FA0B78F81A958E3B000E1D17 /* b64.h */, FA0B78F81A958E3B000E1D17 /* b64.h */,
FA6BDE5B1F31725300786805 /* Color.h */,
FA0B78F91A958E3B000E1D17 /* config.h */, FA0B78F91A958E3B000E1D17 /* config.h */,
FA9D8DD41DEF8411002CD881 /* Data.cpp */, FA9D8DD41DEF8411002CD881 /* Data.cpp */,
FA0B78FA1A958E3B000E1D17 /* Data.h */, FA0B78FA1A958E3B000E1D17 /* Data.h */,
@@ -2660,7 +2651,6 @@
FADF53F71E3C7ACD00012CC0 /* Buffer.h */, FADF53F71E3C7ACD00012CC0 /* Buffer.h */,
FA1BA0A51E16F20600AA2803 /* Canvas.cpp */, FA1BA0A51E16F20600AA2803 /* Canvas.cpp */,
FA1BA0A61E16F20600AA2803 /* Canvas.h */, FA1BA0A61E16F20600AA2803 /* Canvas.h */,
FA0B7B881A95902C000E1D17 /* Color.h */,
FAF1889E1E9DBC4B008C1479 /* depthstencil.cpp */, FAF1889E1E9DBC4B008C1479 /* depthstencil.cpp */,
FAF1889D1E9DBBC8008C1479 /* depthstencil.h */, FAF1889D1E9DBBC8008C1479 /* depthstencil.h */,
FA9D8DDC1DEF842A002CD881 /* Drawable.cpp */, FA9D8DDC1DEF842A002CD881 /* Drawable.cpp */,
@@ -2760,8 +2750,13 @@
FA0B7BC21A95902C000E1D17 /* image */ = { FA0B7BC21A95902C000E1D17 /* image */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
FA93C44F1F315B960087CCD4 /* CompressedFormatHandler.h */,
FA0B7BC31A95902C000E1D17 /* CompressedImageData.cpp */, FA0B7BC31A95902C000E1D17 /* CompressedImageData.cpp */,
FA0B7BC41A95902C000E1D17 /* CompressedImageData.h */, FA0B7BC41A95902C000E1D17 /* CompressedImageData.h */,
FAECA1B01F3164700095D008 /* CompressedSlice.cpp */,
FAECA1B11F3164700095D008 /* CompressedSlice.h */,
FA93C4511F315B960087CCD4 /* FormatHandler.cpp */,
FA93C4501F315B960087CCD4 /* FormatHandler.h */,
FA9D8DDF1DEF843D002CD881 /* Image.cpp */, FA9D8DDF1DEF843D002CD881 /* Image.cpp */,
FA0B7BC51A95902C000E1D17 /* Image.h */, FA0B7BC51A95902C000E1D17 /* Image.h */,
FA0B7BC61A95902C000E1D17 /* ImageData.cpp */, FA0B7BC61A95902C000E1D17 /* ImageData.cpp */,
@@ -2785,19 +2780,10 @@
children = ( children = (
FA41A3C61C0A1F950084430C /* ASTCHandler.cpp */, FA41A3C61C0A1F950084430C /* ASTCHandler.cpp */,
FA41A3C71C0A1F950084430C /* ASTCHandler.h */, FA41A3C71C0A1F950084430C /* ASTCHandler.h */,
FA0B7BCB1A95902C000E1D17 /* CompressedFormatHandler.h */,
FA0B7BC91A95902C000E1D17 /* CompressedImageData.cpp */,
FA0B7BCA1A95902C000E1D17 /* CompressedImageData.h */,
FA0B7BCC1A95902C000E1D17 /* ddsHandler.cpp */, FA0B7BCC1A95902C000E1D17 /* ddsHandler.cpp */,
FA0B7BCD1A95902C000E1D17 /* ddsHandler.h */, FA0B7BCD1A95902C000E1D17 /* ddsHandler.h */,
FA1557C11CE90BD200AFF582 /* EXRHandler.cpp */, FA1557C11CE90BD200AFF582 /* EXRHandler.cpp */,
FA1557C21CE90BD200AFF582 /* EXRHandler.h */, FA1557C21CE90BD200AFF582 /* EXRHandler.h */,
FA0B7BCE1A95902C000E1D17 /* FormatHandler.cpp */,
FA0B7BCF1A95902C000E1D17 /* FormatHandler.h */,
FA0B7BD01A95902C000E1D17 /* Image.cpp */,
FA0B7BD11A95902C000E1D17 /* Image.h */,
FA0B7BD21A95902C000E1D17 /* ImageData.cpp */,
FA0B7BD31A95902C000E1D17 /* ImageData.h */,
FA0B7BD81A95902C000E1D17 /* KTXHandler.cpp */, FA0B7BD81A95902C000E1D17 /* KTXHandler.cpp */,
FA0B7BD91A95902C000E1D17 /* KTXHandler.h */, FA0B7BD91A95902C000E1D17 /* KTXHandler.h */,
FA0B7BDA1A95902C000E1D17 /* PKMHandler.cpp */, FA0B7BDA1A95902C000E1D17 /* PKMHandler.cpp */,
@@ -3550,7 +3536,6 @@
FA76344C1E28722A0066EF9E /* StreamBuffer.h in Headers */, FA76344C1E28722A0066EF9E /* StreamBuffer.h in Headers */,
217DFBF31D9F6D490055D849 /* mime.h in Headers */, 217DFBF31D9F6D490055D849 /* mime.h in Headers */,
FA0B7B361A958EA3000E1D17 /* wuff_convert.h in Headers */, FA0B7B361A958EA3000E1D17 /* wuff_convert.h in Headers */,
FA0B7D981A95902C000E1D17 /* ImageData.h in Headers */,
FA0B7CDE1A95902C000E1D17 /* Source.h in Headers */, FA0B7CDE1A95902C000E1D17 /* Source.h in Headers */,
FA0B7E141A95902C000E1D17 /* GearJoint.h in Headers */, FA0B7E141A95902C000E1D17 /* GearJoint.h in Headers */,
FA0B7D051A95902C000E1D17 /* wrap_DroppedFile.h in Headers */, FA0B7D051A95902C000E1D17 /* wrap_DroppedFile.h in Headers */,
@@ -3612,6 +3597,7 @@
FA0B7CD21A95902C000E1D17 /* Audio.h in Headers */, FA0B7CD21A95902C000E1D17 /* Audio.h in Headers */,
FA0B79421A958E3B000E1D17 /* utf8.h in Headers */, FA0B79421A958E3B000E1D17 /* utf8.h in Headers */,
FA0B7D171A95902C000E1D17 /* Font.h in Headers */, FA0B7D171A95902C000E1D17 /* Font.h in Headers */,
FAECA1B41F3164700095D008 /* CompressedSlice.h in Headers */,
FA0B7A6D1A958EA3000E1D17 /* b2World.h in Headers */, FA0B7A6D1A958EA3000E1D17 /* b2World.h in Headers */,
FA0B7EAE1A95902C000E1D17 /* wrap_SoundData.h in Headers */, FA0B7EAE1A95902C000E1D17 /* wrap_SoundData.h in Headers */,
FA0B7CFF1A95902C000E1D17 /* File.h in Headers */, FA0B7CFF1A95902C000E1D17 /* File.h in Headers */,
@@ -3661,6 +3647,7 @@
FA0B7E351A95902C000E1D17 /* WeldJoint.h in Headers */, FA0B7E351A95902C000E1D17 /* WeldJoint.h in Headers */,
FA0B7E2F1A95902C000E1D17 /* RopeJoint.h in Headers */, FA0B7E2F1A95902C000E1D17 /* RopeJoint.h in Headers */,
FA0B7D141A95902C000E1D17 /* Font.h in Headers */, FA0B7D141A95902C000E1D17 /* Font.h in Headers */,
FA93C4521F315B960087CCD4 /* CompressedFormatHandler.h in Headers */,
FA0B7D411A95902C000E1D17 /* Mesh.h in Headers */, FA0B7D411A95902C000E1D17 /* Mesh.h in Headers */,
FA0B7E591A95902C000E1D17 /* wrap_Joint.h in Headers */, FA0B7E591A95902C000E1D17 /* wrap_Joint.h in Headers */,
FA0B79351A958E3B000E1D17 /* macosx.h in Headers */, FA0B79351A958E3B000E1D17 /* macosx.h in Headers */,
@@ -3668,6 +3655,7 @@
FA0B7E771A95902C000E1D17 /* wrap_WeldJoint.h in Headers */, FA0B7E771A95902C000E1D17 /* wrap_WeldJoint.h in Headers */,
FA0B7A911A958EA3000E1D17 /* b2FrictionJoint.h in Headers */, FA0B7A911A958EA3000E1D17 /* b2FrictionJoint.h in Headers */,
FA0B7E291A95902C000E1D17 /* PulleyJoint.h in Headers */, FA0B7E291A95902C000E1D17 /* PulleyJoint.h in Headers */,
FA6BDE5C1F31725300786805 /* Color.h in Headers */,
FA0B7D471A95902C000E1D17 /* ParticleSystem.h in Headers */, FA0B7D471A95902C000E1D17 /* ParticleSystem.h in Headers */,
FA0B7E231A95902C000E1D17 /* PolygonShape.h in Headers */, FA0B7E231A95902C000E1D17 /* PolygonShape.h in Headers */,
FA0B791E1A958E3B000E1D17 /* config.h in Headers */, FA0B791E1A958E3B000E1D17 /* config.h in Headers */,
@@ -3720,6 +3708,7 @@
FA0B7ECD1A95902C000E1D17 /* wrap_Channel.h in Headers */, FA0B7ECD1A95902C000E1D17 /* wrap_Channel.h in Headers */,
FAF140AF1E20934C00F898D2 /* osinclude.h in Headers */, FAF140AF1E20934C00F898D2 /* osinclude.h in Headers */,
FA0B7A431A958EA3000E1D17 /* b2CircleShape.h in Headers */, FA0B7A431A958EA3000E1D17 /* b2CircleShape.h in Headers */,
FA93C4531F315B960087CCD4 /* FormatHandler.h in Headers */,
FA0B7CD81A95902C000E1D17 /* Audio.h in Headers */, FA0B7CD81A95902C000E1D17 /* Audio.h in Headers */,
FA0B7CF61A95902C000E1D17 /* File.h in Headers */, FA0B7CF61A95902C000E1D17 /* File.h in Headers */,
FA0B7E961A95902C000E1D17 /* Mpg123Decoder.h in Headers */, FA0B7E961A95902C000E1D17 /* Mpg123Decoder.h in Headers */,
@@ -3728,7 +3717,6 @@
FA0B7DD51A95902C000E1D17 /* BezierCurve.h in Headers */, FA0B7DD51A95902C000E1D17 /* BezierCurve.h in Headers */,
FA0B79271A958E3B000E1D17 /* int.h in Headers */, FA0B79271A958E3B000E1D17 /* int.h in Headers */,
FA27B3A21B498151008A9DCE /* VideoStream.h in Headers */, FA27B3A21B498151008A9DCE /* VideoStream.h in Headers */,
FA0B7D8C1A95902C000E1D17 /* CompressedFormatHandler.h in Headers */,
FA0B7E531A95902C000E1D17 /* wrap_FrictionJoint.h in Headers */, FA0B7E531A95902C000E1D17 /* wrap_FrictionJoint.h in Headers */,
FA0B7EB71A95902C000E1D17 /* wrap_System.h in Headers */, FA0B7EB71A95902C000E1D17 /* wrap_System.h in Headers */,
FA27B3A91B498151008A9DCE /* Video.h in Headers */, FA27B3A91B498151008A9DCE /* Video.h in Headers */,
@@ -3738,7 +3726,6 @@
FAB17BF21ABFB37500F9BA27 /* wrap_CompressedData.h in Headers */, FAB17BF21ABFB37500F9BA27 /* wrap_CompressedData.h in Headers */,
FA0B7E801A95902C000E1D17 /* Joint.h in Headers */, FA0B7E801A95902C000E1D17 /* Joint.h in Headers */,
FA0B7D2F1A95902C000E1D17 /* Drawable.h in Headers */, FA0B7D2F1A95902C000E1D17 /* Drawable.h in Headers */,
FA0B7D951A95902C000E1D17 /* Image.h in Headers */,
217DFBE21D9F6D490055D849 /* ftp.lua.h in Headers */, 217DFBE21D9F6D490055D849 /* ftp.lua.h in Headers */,
FA0B7EC41A95902C000E1D17 /* Thread.h in Headers */, FA0B7EC41A95902C000E1D17 /* Thread.h in Headers */,
FA0B7DFF1A95902C000E1D17 /* ChainShape.h in Headers */, FA0B7DFF1A95902C000E1D17 /* ChainShape.h in Headers */,
@@ -3794,7 +3781,6 @@
FA0B7CF91A95902C000E1D17 /* FileData.h in Headers */, FA0B7CF91A95902C000E1D17 /* FileData.h in Headers */,
FA0B7DA71A95902C000E1D17 /* PNGHandler.h in Headers */, FA0B7DA71A95902C000E1D17 /* PNGHandler.h in Headers */,
FA0B7AC41A958EA3000E1D17 /* protocol.h in Headers */, FA0B7AC41A958EA3000E1D17 /* protocol.h in Headers */,
FA0B7D8B1A95902C000E1D17 /* CompressedImageData.h in Headers */,
FAF140601E20934C00F898D2 /* revision.h in Headers */, FAF140601E20934C00F898D2 /* revision.h in Headers */,
FAF140A21E20934C00F898D2 /* RemoveTree.h in Headers */, FAF140A21E20934C00F898D2 /* RemoveTree.h in Headers */,
FA0B7A8E1A958EA3000E1D17 /* b2DistanceJoint.h in Headers */, FA0B7A8E1A958EA3000E1D17 /* b2DistanceJoint.h in Headers */,
@@ -3876,7 +3862,6 @@
FA9D8DD31DEB56C3002CD881 /* pixelformat.h in Headers */, FA9D8DD31DEB56C3002CD881 /* pixelformat.h in Headers */,
FAF140A61E20934C00F898D2 /* ScanContext.h in Headers */, FAF140A61E20934C00F898D2 /* ScanContext.h in Headers */,
FA0B7E4A1A95902C000E1D17 /* wrap_DistanceJoint.h in Headers */, FA0B7E4A1A95902C000E1D17 /* wrap_DistanceJoint.h in Headers */,
FA0B7D2E1A95902C000E1D17 /* Color.h in Headers */,
FA0B7A6A1A958EA3000E1D17 /* b2TimeStep.h in Headers */, FA0B7A6A1A958EA3000E1D17 /* b2TimeStep.h in Headers */,
FA0B7A281A958EA3000E1D17 /* Box2D.h in Headers */, FA0B7A281A958EA3000E1D17 /* Box2D.h in Headers */,
FA0B7DE41A95902C000E1D17 /* wrap_RandomGenerator.h in Headers */, FA0B7DE41A95902C000E1D17 /* wrap_RandomGenerator.h in Headers */,
@@ -3895,7 +3880,6 @@
FADF54041E3D77B500012CC0 /* wrap_Text.h in Headers */, FADF54041E3D77B500012CC0 /* wrap_Text.h in Headers */,
FA0B7ED31A95902C000E1D17 /* wrap_ThreadModule.h in Headers */, FA0B7ED31A95902C000E1D17 /* wrap_ThreadModule.h in Headers */,
FA0B7A511A958EA3000E1D17 /* b2GrowableStack.h in Headers */, FA0B7A511A958EA3000E1D17 /* b2GrowableStack.h in Headers */,
FA0B7D921A95902C000E1D17 /* FormatHandler.h in Headers */,
FAC756F61E4F99B400B91289 /* Effect.h in Headers */, FAC756F61E4F99B400B91289 /* Effect.h in Headers */,
FA0B7ADD1A958EA3000E1D17 /* gladfuncs.hpp in Headers */, FA0B7ADD1A958EA3000E1D17 /* gladfuncs.hpp in Headers */,
FAF1405D1E20934C00F898D2 /* intermediate.h in Headers */, FAF1405D1E20934C00F898D2 /* intermediate.h in Headers */,
@@ -4051,7 +4035,6 @@
FA0B7ABE1A958EA3000E1D17 /* compress.c in Sources */, FA0B7ABE1A958EA3000E1D17 /* compress.c in Sources */,
FA0B7CF21A95902C000E1D17 /* DroppedFile.cpp in Sources */, FA0B7CF21A95902C000E1D17 /* DroppedFile.cpp in Sources */,
FA4F2C141DE936FE00CA37D7 /* usocket.c in Sources */, FA4F2C141DE936FE00CA37D7 /* usocket.c in Sources */,
FA0B7D8A1A95902C000E1D17 /* CompressedImageData.cpp in Sources */,
FAF140831E20934C00F898D2 /* ParseContextBase.cpp in Sources */, FAF140831E20934C00F898D2 /* ParseContextBase.cpp in Sources */,
FA0B7AD21A958EA3000E1D17 /* protocol.c in Sources */, FA0B7AD21A958EA3000E1D17 /* protocol.c in Sources */,
FAF140A41E20934C00F898D2 /* Scan.cpp in Sources */, FAF140A41E20934C00F898D2 /* Scan.cpp in Sources */,
@@ -4190,15 +4173,14 @@
FADF54211E3DA52C00012CC0 /* wrap_ParticleSystem.cpp in Sources */, FADF54211E3DA52C00012CC0 /* wrap_ParticleSystem.cpp in Sources */,
FA0B791C1A958E3B000E1D17 /* b64.cpp in Sources */, FA0B791C1A958E3B000E1D17 /* b64.cpp in Sources */,
FA1E88851DF363E100E808AA /* Filter.cpp in Sources */, FA1E88851DF363E100E808AA /* Filter.cpp in Sources */,
FA0B7D941A95902C000E1D17 /* Image.cpp in Sources */,
FA0B7DA01A95902C000E1D17 /* KTXHandler.cpp in Sources */, FA0B7DA01A95902C000E1D17 /* KTXHandler.cpp in Sources */,
FA27B3A11B498151008A9DCE /* VideoStream.cpp in Sources */, FA27B3A11B498151008A9DCE /* VideoStream.cpp in Sources */,
FA0B7A5C1A958EA3000E1D17 /* b2Timer.cpp in Sources */, FA0B7A5C1A958EA3000E1D17 /* b2Timer.cpp in Sources */,
FA0B7CEC1A95902C000E1D17 /* Event.cpp in Sources */, FA0B7CEC1A95902C000E1D17 /* Event.cpp in Sources */,
FA27B3AB1B498151008A9DCE /* VideoStream.cpp in Sources */, FA27B3AB1B498151008A9DCE /* VideoStream.cpp in Sources */,
FA0B7A7E1A958EA3000E1D17 /* b2ContactSolver.cpp in Sources */, FA0B7A7E1A958EA3000E1D17 /* b2ContactSolver.cpp in Sources */,
FA0B7D971A95902C000E1D17 /* ImageData.cpp in Sources */,
FA0B7E581A95902C000E1D17 /* wrap_Joint.cpp in Sources */, FA0B7E581A95902C000E1D17 /* wrap_Joint.cpp in Sources */,
FAECA1B51F31648A0095D008 /* FormatHandler.cpp in Sources */,
FA4F2C0A1DE936E600CA37D7 /* mime.c in Sources */, FA4F2C0A1DE936E600CA37D7 /* mime.c in Sources */,
FA0B7E311A95902C000E1D17 /* Shape.cpp in Sources */, FA0B7E311A95902C000E1D17 /* Shape.cpp in Sources */,
FA0B7E491A95902C000E1D17 /* wrap_DistanceJoint.cpp in Sources */, FA0B7E491A95902C000E1D17 /* wrap_DistanceJoint.cpp in Sources */,
@@ -4287,13 +4269,13 @@
FA0B7DB21A95902C000E1D17 /* wrap_Image.cpp in Sources */, FA0B7DB21A95902C000E1D17 /* wrap_Image.cpp in Sources */,
FA0B7E891A95902C000E1D17 /* Decoder.cpp in Sources */, FA0B7E891A95902C000E1D17 /* Decoder.cpp in Sources */,
FA0B7A591A958EA3000E1D17 /* b2StackAllocator.cpp in Sources */, FA0B7A591A958EA3000E1D17 /* b2StackAllocator.cpp in Sources */,
FAECA1B31F3164700095D008 /* CompressedSlice.cpp in Sources */,
FA0B7E3D1A95902C000E1D17 /* wrap_Body.cpp in Sources */, FA0B7E3D1A95902C000E1D17 /* wrap_Body.cpp in Sources */,
FA0B7D7A1A95902C000E1D17 /* Quad.cpp in Sources */, FA0B7D7A1A95902C000E1D17 /* Quad.cpp in Sources */,
FA620A3B1AA305F6005DB4C2 /* types.cpp in Sources */, FA620A3B1AA305F6005DB4C2 /* types.cpp in Sources */,
FA0B7DD41A95902C000E1D17 /* BezierCurve.cpp in Sources */, FA0B7DD41A95902C000E1D17 /* BezierCurve.cpp in Sources */,
FA0B7E7C1A95902C000E1D17 /* wrap_World.cpp in Sources */, FA0B7E7C1A95902C000E1D17 /* wrap_World.cpp in Sources */,
FA4F2C0E1DE936FE00CA37D7 /* tcp.c in Sources */, FA4F2C0E1DE936FE00CA37D7 /* tcp.c in Sources */,
FA0B7D911A95902C000E1D17 /* FormatHandler.cpp in Sources */,
FA0B7D431A95902C000E1D17 /* OpenGL.cpp in Sources */, FA0B7D431A95902C000E1D17 /* OpenGL.cpp in Sources */,
FA0B7DBF1A95902C000E1D17 /* JoystickModule.cpp in Sources */, FA0B7DBF1A95902C000E1D17 /* JoystickModule.cpp in Sources */,
FA0B7D4F1A95902C000E1D17 /* SpriteBatch.cpp in Sources */, FA0B7D4F1A95902C000E1D17 /* SpriteBatch.cpp in Sources */,
@@ -4410,7 +4392,6 @@
FA0B7D091A95902C000E1D17 /* wrap_FileData.cpp in Sources */, FA0B7D091A95902C000E1D17 /* wrap_FileData.cpp in Sources */,
FA0B7B341A958EA3000E1D17 /* wuff_convert.c in Sources */, FA0B7B341A958EA3000E1D17 /* wuff_convert.c in Sources */,
FA0B7CF11A95902C000E1D17 /* DroppedFile.cpp in Sources */, FA0B7CF11A95902C000E1D17 /* DroppedFile.cpp in Sources */,
FA0B7D891A95902C000E1D17 /* CompressedImageData.cpp in Sources */,
FAF140821E20934C00F898D2 /* ParseContextBase.cpp in Sources */, FAF140821E20934C00F898D2 /* ParseContextBase.cpp in Sources */,
FA0B7D1E1A95902C000E1D17 /* ImageRasterizer.cpp in Sources */, FA0B7D1E1A95902C000E1D17 /* ImageRasterizer.cpp in Sources */,
FAF140A31E20934C00F898D2 /* Scan.cpp in Sources */, FAF140A31E20934C00F898D2 /* Scan.cpp in Sources */,
@@ -4545,7 +4526,6 @@
FA0B7A4E1A958EA3000E1D17 /* b2Draw.cpp in Sources */, FA0B7A4E1A958EA3000E1D17 /* b2Draw.cpp in Sources */,
FAD19A171DFF8CA200D5398A /* ImageDataBase.cpp in Sources */, FAD19A171DFF8CA200D5398A /* ImageDataBase.cpp in Sources */,
FA27B3C01B4985BF008A9DCE /* wrap_VideoStream.cpp in Sources */, FA27B3C01B4985BF008A9DCE /* wrap_VideoStream.cpp in Sources */,
FA0B7D931A95902C000E1D17 /* Image.cpp in Sources */,
FADF54201E3DA52C00012CC0 /* wrap_ParticleSystem.cpp in Sources */, FADF54201E3DA52C00012CC0 /* wrap_ParticleSystem.cpp in Sources */,
FA0B7D9F1A95902C000E1D17 /* KTXHandler.cpp in Sources */, FA0B7D9F1A95902C000E1D17 /* KTXHandler.cpp in Sources */,
FA1E88831DF363DB00E808AA /* Filter.cpp in Sources */, FA1E88831DF363DB00E808AA /* Filter.cpp in Sources */,
@@ -4554,9 +4534,9 @@
FA0B7CEB1A95902C000E1D17 /* Event.cpp in Sources */, FA0B7CEB1A95902C000E1D17 /* Event.cpp in Sources */,
FA1557C31CE90BD200AFF582 /* EXRHandler.cpp in Sources */, FA1557C31CE90BD200AFF582 /* EXRHandler.cpp in Sources */,
FA27B3AA1B498151008A9DCE /* VideoStream.cpp in Sources */, FA27B3AA1B498151008A9DCE /* VideoStream.cpp in Sources */,
FA0B7D961A95902C000E1D17 /* ImageData.cpp in Sources */,
FA0B7E571A95902C000E1D17 /* wrap_Joint.cpp in Sources */, FA0B7E571A95902C000E1D17 /* wrap_Joint.cpp in Sources */,
FA0B7E301A95902C000E1D17 /* Shape.cpp in Sources */, FA0B7E301A95902C000E1D17 /* Shape.cpp in Sources */,
FA93C4541F315B960087CCD4 /* FormatHandler.cpp in Sources */,
FA0B7E481A95902C000E1D17 /* wrap_DistanceJoint.cpp in Sources */, FA0B7E481A95902C000E1D17 /* wrap_DistanceJoint.cpp in Sources */,
FA0B7A8F1A958EA3000E1D17 /* b2FrictionJoint.cpp in Sources */, FA0B7A8F1A958EA3000E1D17 /* b2FrictionJoint.cpp in Sources */,
FA0B792F1A958E3B000E1D17 /* Module.cpp in Sources */, FA0B792F1A958E3B000E1D17 /* Module.cpp in Sources */,
@@ -4597,6 +4577,7 @@
FA0B7E8B1A95902C000E1D17 /* FLACDecoder.cpp in Sources */, FA0B7E8B1A95902C000E1D17 /* FLACDecoder.cpp in Sources */,
FA0B7B3A1A958EA3000E1D17 /* wuff_memory.c in Sources */, FA0B7B3A1A958EA3000E1D17 /* wuff_memory.c in Sources */,
FA0B7A381A958EA3000E1D17 /* b2DynamicTree.cpp in Sources */, FA0B7A381A958EA3000E1D17 /* b2DynamicTree.cpp in Sources */,
FAECA1B21F3164700095D008 /* CompressedSlice.cpp in Sources */,
FA0B7D481A95902C000E1D17 /* Polyline.cpp in Sources */, FA0B7D481A95902C000E1D17 /* Polyline.cpp in Sources */,
217DFC111D9F6D490055D849 /* usocket.c in Sources */, 217DFC111D9F6D490055D849 /* usocket.c in Sources */,
FAF140751E20934C00F898D2 /* IntermTraverse.cpp in Sources */, FAF140751E20934C00F898D2 /* IntermTraverse.cpp in Sources */,
@@ -4647,7 +4628,6 @@
FA91591E1CF1ED7500A7053F /* halffloat.cpp in Sources */, FA91591E1CF1ED7500A7053F /* halffloat.cpp in Sources */,
FA0B7E7B1A95902C000E1D17 /* wrap_World.cpp in Sources */, FA0B7E7B1A95902C000E1D17 /* wrap_World.cpp in Sources */,
FA0B7B281A958EA3000E1D17 /* simplexnoise1234.cpp in Sources */, FA0B7B281A958EA3000E1D17 /* simplexnoise1234.cpp in Sources */,
FA0B7D901A95902C000E1D17 /* FormatHandler.cpp in Sources */,
FA0B7D421A95902C000E1D17 /* OpenGL.cpp in Sources */, FA0B7D421A95902C000E1D17 /* OpenGL.cpp in Sources */,
FA0B7A671A958EA3000E1D17 /* b2Island.cpp in Sources */, FA0B7A671A958EA3000E1D17 /* b2Island.cpp in Sources */,
FA0B7DBE1A95902C000E1D17 /* JoystickModule.cpp in Sources */, FA0B7DBE1A95902C000E1D17 /* JoystickModule.cpp in Sources */,
@@ -17,6 +17,7 @@
A9D307F2106635D3004FEDF8 /* physfs.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9D307E9106635C3004FEDF8 /* physfs.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; A9D307F2106635D3004FEDF8 /* physfs.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9D307E9106635C3004FEDF8 /* physfs.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
A9F169AC109E825000FC83D1 /* mpg123.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9F169A6109E824900FC83D1 /* mpg123.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; A9F169AC109E825000FC83D1 /* mpg123.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9F169A6109E824900FC83D1 /* mpg123.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
A9F169AD109E825000FC83D1 /* libmodplug.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9F16926109E7BAD00FC83D1 /* libmodplug.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; A9F169AD109E825000FC83D1 /* libmodplug.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = A9F16926109E7BAD00FC83D1 /* libmodplug.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
CE73F8001EEB64150052DAB3 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE73F7FF1EEB64150052DAB3 /* AVFoundation.framework */; };
FA0797991BF480A200034B7C /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA0797981BF480A200034B7C /* GameController.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; FA0797991BF480A200034B7C /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA0797981BF480A200034B7C /* GameController.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
FA08F69616C766E000F007B5 /* love.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA08F69116C765A200F007B5 /* love.framework */; }; FA08F69616C766E000F007B5 /* love.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA08F69116C765A200F007B5 /* love.framework */; };
FA08F69716C766E700F007B5 /* love.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = FA08F69116C765A200F007B5 /* love.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; FA08F69716C766E700F007B5 /* love.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = FA08F69116C765A200F007B5 /* love.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
@@ -110,6 +111,7 @@
A9D307E9106635C3004FEDF8 /* physfs.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = physfs.framework; path = /Library/Frameworks/physfs.framework; sourceTree = "<absolute>"; }; A9D307E9106635C3004FEDF8 /* physfs.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = physfs.framework; path = /Library/Frameworks/physfs.framework; sourceTree = "<absolute>"; };
A9F16926109E7BAD00FC83D1 /* libmodplug.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = libmodplug.framework; path = /Library/Frameworks/libmodplug.framework; sourceTree = "<absolute>"; }; A9F16926109E7BAD00FC83D1 /* libmodplug.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = libmodplug.framework; path = /Library/Frameworks/libmodplug.framework; sourceTree = "<absolute>"; };
A9F169A6109E824900FC83D1 /* mpg123.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = mpg123.framework; path = /Library/Frameworks/mpg123.framework; sourceTree = "<absolute>"; }; A9F169A6109E824900FC83D1 /* mpg123.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = mpg123.framework; path = /Library/Frameworks/mpg123.framework; sourceTree = "<absolute>"; };
CE73F7FF1EEB64150052DAB3 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/AVFoundation.framework; sourceTree = DEVELOPER_DIR; };
FA0797981BF480A200034B7C /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.1.sdk/System/Library/Frameworks/GameController.framework; sourceTree = DEVELOPER_DIR; }; FA0797981BF480A200034B7C /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.1.sdk/System/Library/Frameworks/GameController.framework; sourceTree = DEVELOPER_DIR; };
FA08F69116C765A200F007B5 /* love.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = love.framework; sourceTree = BUILT_PRODUCTS_DIR; }; FA08F69116C765A200F007B5 /* love.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = love.framework; sourceTree = BUILT_PRODUCTS_DIR; };
FA0B7F061A95AAF3000E1D17 /* love.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = love.app; sourceTree = BUILT_PRODUCTS_DIR; }; FA0B7F061A95AAF3000E1D17 /* love.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = love.app; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -149,6 +151,7 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
CE73F8001EEB64150052DAB3 /* AVFoundation.framework in Frameworks */,
FA5D24D11A96E73300C6FC8F /* liblove.a in Frameworks */, FA5D24D11A96E73300C6FC8F /* liblove.a in Frameworks */,
FA5D24C21A96D78000C6FC8F /* Foundation.framework in Frameworks */, FA5D24C21A96D78000C6FC8F /* Foundation.framework in Frameworks */,
FA5D24961A96CAC200C6FC8F /* CoreMotion.framework in Frameworks */, FA5D24961A96CAC200C6FC8F /* CoreMotion.framework in Frameworks */,
@@ -169,6 +172,7 @@
1058C7A0FEA54F0111CA2CBB /* Frameworks */ = { 1058C7A0FEA54F0111CA2CBB /* Frameworks */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
CE73F7FF1EEB64150052DAB3 /* AVFoundation.framework */,
FA5D24801A96C97900C6FC8F /* ios */, FA5D24801A96C97900C6FC8F /* ios */,
FA0B7EEC1A959249000E1D17 /* macosx */, FA0B7EEC1A959249000E1D17 /* macosx */,
); );
@@ -18,13 +18,11 @@
* 3. This notice may not be removed or altered from any source distribution. * 3. This notice may not be removed or altered from any source distribution.
**/ **/
#ifndef LOVE_GRAPHICS_COLOR_H #ifndef LOVE_COLOR_H
#define LOVE_GRAPHICS_COLOR_H #define LOVE_COLOR_H
namespace love namespace love
{ {
namespace graphics
{
template <typename T> template <typename T>
struct ColorT struct ColorT
@@ -153,7 +151,6 @@ inline Colorf toColorf(Color c)
return Colorf(c.r / 255.0f, c.g / 255.0f, c.b / 255.0f, c.a / 255.0f); return Colorf(c.r / 255.0f, c.g / 255.0f, c.b / 255.0f, c.a / 255.0f);
} }
} // graphics
} // love } // love
#endif // LOVE_GRAPHICS_COLOR_H #endif // LOVE_COLOR_H
+16
View File
@@ -225,6 +225,22 @@ bool createStorageDirectories()
return true; return true;
} }
bool hasBackgroundMusic()
{
JNIEnv *env = (JNIEnv*) SDL_AndroidGetJNIEnv();
jobject activity = (jobject) SDL_AndroidGetActivity();
jclass clazz(env->GetObjectClass(activity));
jmethodID method_id = env->GetMethodID(clazz, "hasBackgroundMusic", "()Z");
jboolean result = env->CallBooleanMethod(activity, method_id);
env->DeleteLocalRef(activity);
env->DeleteLocalRef(clazz);
return result;
}
} // android } // android
} // love } // love
+2
View File
@@ -66,6 +66,8 @@ bool mkdir(const char *path);
bool createStorageDirectories(); bool createStorageDirectories();
bool hasBackgroundMusic();
} // android } // android
} // love } // love
+10
View File
@@ -64,6 +64,16 @@ std::string getExecutablePath();
**/ **/
void vibrate(); void vibrate();
/**
* Enable mix mode (e.g. with background music apps) and playback with a muted device.
**/
void setAudioMixWithOthers(bool mixEnabled);
/**
* Returns whether another application is playing audio.
**/
bool hasBackgroundMusic();
} // ios } // ios
} // love } // love
+23
View File
@@ -26,6 +26,7 @@
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#import <AudioToolbox/AudioServices.h> #import <AudioToolbox/AudioServices.h>
#import <AVFoundation/AVFoundation.h>
#include <vector> #include <vector>
@@ -344,6 +345,28 @@ void vibrate()
} }
} }
void setAudioMixWithOthers(bool mixEnabled)
{
@autoreleasepool
{
NSString *category = AVAudioSessionCategorySoloAmbient;
NSError *err;
if (mixEnabled)
category = AVAudioSessionCategoryAmbient;
if (![[AVAudioSession sharedInstance] setCategory:category error:&err])
NSLog(@"Error in AVAudioSession setCategory: %@", [err localizedDescription]);
}
}
bool hasBackgroundMusic()
{
if ([[AVAudioSession sharedInstance] respondsToSelector:@selector(secondaryAudioShouldBeSilencedHint)])
return [[AVAudioSession sharedInstance] secondaryAudioShouldBeSilencedHint];
return false;
}
} // ios } // ios
} // love } // love
+14 -16
View File
@@ -1,25 +1,23 @@
/** /**
* Simple DDS data parser for compressed 2D textures. * Simple DDS data parser for compressed 2D textures.
* *
* Copyright (c) 2013 Alexander Szpakowski. * Copyright (c) 2013-2017 Alex Szpakowski
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * This software is provided 'as-is', without any express or implied
* of this software and associated documentation files (the "Software"), to deal * warranty. In no event will the authors be held liable for any damages
* in the Software without restriction, including without limitation the rights * arising from the use of this software.
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * Permission is granted to anyone to use this software for any purpose,
* all copies or substantial portions of the Software. * including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * 1. The origin of this software must not be misrepresented; you must not
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * claim that you wrote the original software. If you use this software
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * in a product, an acknowledgment in the product documentation would be
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * appreciated but is not required.
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * 2. Altered source versions must be plainly marked as such, and must not be
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * misrepresented as being the original software.
* THE SOFTWARE. * 3. This notice may not be removed or altered from any source distribution.
* *
* *
* Enums and structs copied from Microsoft. * Enums and structs copied from Microsoft.
+14 -16
View File
@@ -1,25 +1,23 @@
/** /**
* Simple DDS data parser for compressed 2D textures. * Simple DDS data parser for compressed 2D textures.
* *
* Copyright (c) 2013 Alexander Szpakowski. * Copyright (c) 2013-2017 Alex Szpakowski
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * This software is provided 'as-is', without any express or implied
* of this software and associated documentation files (the "Software"), to deal * warranty. In no event will the authors be held liable for any damages
* in the Software without restriction, including without limitation the rights * arising from the use of this software.
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * Permission is granted to anyone to use this software for any purpose,
* all copies or substantial portions of the Software. * including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * 1. The origin of this software must not be misrepresented; you must not
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * claim that you wrote the original software. If you use this software
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * in a product, an acknowledgment in the product documentation would be
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * appreciated but is not required.
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * 2. Altered source versions must be plainly marked as such, and must not be
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * misrepresented as being the original software.
* THE SOFTWARE. * 3. This notice may not be removed or altered from any source distribution.
**/ **/
#include "ddsparse.h" #include "ddsparse.h"
+14 -16
View File
@@ -1,25 +1,23 @@
/** /**
* Simple DDS data parser for compressed 2D textures. * Simple DDS data parser for compressed 2D textures.
* *
* Copyright (c) 2013 Alexander Szpakowski. * Copyright (c) 2013-2017 Alex Szpakowski
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * This software is provided 'as-is', without any express or implied
* of this software and associated documentation files (the "Software"), to deal * warranty. In no event will the authors be held liable for any damages
* in the Software without restriction, including without limitation the rights * arising from the use of this software.
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * Permission is granted to anyone to use this software for any purpose,
* all copies or substantial portions of the Software. * including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * 1. The origin of this software must not be misrepresented; you must not
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * claim that you wrote the original software. If you use this software
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * in a product, an acknowledgment in the product documentation would be
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * appreciated but is not required.
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * 2. Altered source versions must be plainly marked as such, and must not be
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * misrepresented as being the original software.
* THE SOFTWARE. * 3. This notice may not be removed or altered from any source distribution.
**/ **/
#ifndef DDS_PARSE_H #ifndef DDS_PARSE_H
File diff suppressed because it is too large Load Diff
+18 -2
View File
@@ -13,18 +13,34 @@
* claim that you wrote the original software. If you use this software * claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be * in a product, an acknowledgment in the product documentation would be
* appreciated but is not required. * appreciated but is not required.
* 2. Altered Audio versions must be plainly marked as such, and must not be * 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software. * misrepresented as being the original software.
* 3. This notice may not be removed or altered from any Audio distribution. * 3. This notice may not be removed or altered from any source distribution.
**/ **/
#include "Audio.h" #include "Audio.h"
#include "common/config.h"
#ifdef LOVE_IOS
#include "common/ios.h"
#endif
namespace love namespace love
{ {
namespace audio namespace audio
{ {
bool Audio::setMixWithSystem(bool mix)
{
#ifdef LOVE_IOS
love::ios::setAudioMixWithOthers(mix);
return true;
#else
LOVE_UNUSED(mix);
return false;
#endif
}
StringMap<Audio::DistanceModel, Audio::DISTANCE_MAX_ENUM>::Entry Audio::distanceModelEntries[] = StringMap<Audio::DistanceModel, Audio::DISTANCE_MAX_ENUM>::Entry Audio::distanceModelEntries[] =
{ {
{"none", Audio::DISTANCE_NONE}, {"none", Audio::DISTANCE_NONE},
+8 -2
View File
@@ -9,7 +9,7 @@
* including commercial applications, and to alter it and redistribute it * including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions: * freely, subject to the following restrictions:
* *
* 1. The origin of this software must not be misrepresented = 0; you must not * 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 * claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be * in a product, an acknowledgment in the product documentation would be
* appreciated but is not required. * appreciated but is not required.
@@ -236,7 +236,7 @@ public:
* @param list List of EFX names to fill. * @param list List of EFX names to fill.
* @return true if effect was present, false otherwise. * @return true if effect was present, false otherwise.
*/ */
virtual bool getEffectsList(std::vector<std::string> &list) = 0; virtual bool getActiveEffects(std::vector<std::string> &list) const = 0;
/** /**
* Gets maximum number of scene EFX effects. * Gets maximum number of scene EFX effects.
@@ -256,6 +256,12 @@ public:
*/ */
virtual bool isEFXsupported() const = 0; virtual bool isEFXsupported() const = 0;
/**
* Sets whether audio from other apps mixes with love.audio or is muted,
* on supported platforms.
**/
bool setMixWithSystem(bool mix);
private: private:
static StringMap<DistanceModel, DISTANCE_MAX_ENUM>::Entry distanceModelEntries[]; static StringMap<DistanceModel, DISTANCE_MAX_ENUM>::Entry distanceModelEntries[];
+1 -1
View File
@@ -1,5 +1,5 @@
/** /**
* Copyright (c) 2006-2016 LOVE Development Team * Copyright (c) 2006-2017 LOVE Development Team
* *
* This software is provided 'as-is', without any express or implied * This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages * warranty. In no event will the authors be held liable for any damages
+1 -1
View File
@@ -1,5 +1,5 @@
/** /**
* Copyright (c) 2006-2016 LOVE Development Team * Copyright (c) 2006-2017 LOVE Development Team
* *
* This software is provided 'as-is', without any express or implied * This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages * warranty. In no event will the authors be held liable for any damages
+12 -7
View File
@@ -9,7 +9,7 @@
* including commercial applications, and to alter it and redistribute it * including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions: * freely, subject to the following restrictions:
* *
* 1. The origin of this software must not be misrepresented = 0; you must not * 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 * claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be * in a product, an acknowledgment in the product documentation would be
* appreciated but is not required. * appreciated but is not required.
@@ -37,15 +37,14 @@ public:
static love::Type type; static love::Type type;
static const int DEFAULT_SAMPLES = 8192;
static const int DEFAULT_SAMPLE_RATE = 8000;
static const int DEFAULT_BIT_DEPTH = 16;
static const int DEFAULT_CHANNELS = 1;
RecordingDevice(); RecordingDevice();
virtual ~RecordingDevice(); virtual ~RecordingDevice();
/**
* Begins audio input recording process. using default (previous) parameters.
* @return True if recording started successfully.
**/
virtual bool start() = 0;
/** /**
* Begins audio input recording process. * Begins audio input recording process.
* @param samples Number of samples to buffer. * @param samples Number of samples to buffer.
@@ -77,6 +76,11 @@ public:
**/ **/
virtual int getSampleCount() const = 0; virtual int getSampleCount() const = 0;
/**
* Gets the maximum number of samples that will be buffered, as set by start().
**/
virtual int getMaxSamples() const = 0;
/** /**
* @return Sample rate for recording. * @return Sample rate for recording.
**/ **/
@@ -96,6 +100,7 @@ public:
* @return True if currently recording. * @return True if currently recording.
**/ **/
virtual bool isRecording() const = 0; virtual bool isRecording() const = 0;
}; //RecordingDevice }; //RecordingDevice
} //audio } //audio
+1 -1
View File
@@ -117,7 +117,7 @@ public:
virtual bool setEffect(const char *effect, const std::map<Filter::Parameter, float> &params) = 0; virtual bool setEffect(const char *effect, const std::map<Filter::Parameter, float> &params) = 0;
virtual bool unsetEffect(const char *effect) = 0; virtual bool unsetEffect(const char *effect) = 0;
virtual bool getEffect(const char *effect, std::map<Filter::Parameter, float> &params) = 0; virtual bool getEffect(const char *effect, std::map<Filter::Parameter, float> &params) = 0;
virtual bool getEffectsList(std::vector<std::string> &list) = 0; virtual bool getActiveEffects(std::vector<std::string> &list) const = 0;
virtual int getFreeBufferCount() const = 0; virtual int getFreeBufferCount() const = 0;
virtual bool queue(void *data, size_t length, int dataSampleRate, int dataBitDepth, int dataChannels) = 0; virtual bool queue(void *data, size_t length, int dataSampleRate, int dataBitDepth, int dataChannels) = 0;
+1 -1
View File
@@ -183,7 +183,7 @@ bool Audio::getEffect(const char *, std::map<Effect::Parameter, float> &)
return false; return false;
} }
bool Audio::getEffectsList(std::vector<std::string> &list) bool Audio::getActiveEffects(std::vector<std::string> &) const
{ {
return false; return false;
} }
+1 -1
View File
@@ -81,7 +81,7 @@ public:
bool setEffect(const char *, std::map<Effect::Parameter, float> &params); bool setEffect(const char *, std::map<Effect::Parameter, float> &params);
bool unsetEffect(const char *); bool unsetEffect(const char *);
bool getEffect(const char *, std::map<Effect::Parameter, float> &params); bool getEffect(const char *, std::map<Effect::Parameter, float> &params);
bool getEffectsList(std::vector<std::string> &list); bool getActiveEffects(std::vector<std::string> &list) const;
int getMaxSceneEffects() const; int getMaxSceneEffects() const;
int getMaxSourceEffects() const; int getMaxSourceEffects() const;
bool isEFXsupported() const; bool isEFXsupported() const;
+9 -9
View File
@@ -9,7 +9,7 @@
* including commercial applications, and to alter it and redistribute it * including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions: * freely, subject to the following restrictions:
* *
* 1. The origin of this software must not be misrepresented = 0; you must not * 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 * claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be * in a product, an acknowledgment in the product documentation would be
* appreciated but is not required. * appreciated but is not required.
@@ -38,11 +38,6 @@ RecordingDevice::~RecordingDevice()
{ {
} }
bool RecordingDevice::start()
{
return false;
}
bool RecordingDevice::start(int, int, int, int) bool RecordingDevice::start(int, int, int, int)
{ {
return false; return false;
@@ -62,19 +57,24 @@ int RecordingDevice::getSampleCount() const
return 0; return 0;
} }
int RecordingDevice::getMaxSamples() const
{
return 0;
}
int RecordingDevice::getSampleRate() const int RecordingDevice::getSampleRate() const
{ {
return 8000; return 0;
} }
int RecordingDevice::getBitDepth() const int RecordingDevice::getBitDepth() const
{ {
return 16; return 0;
} }
int RecordingDevice::getChannels() const int RecordingDevice::getChannels() const
{ {
return 1; return 0;
} }
const char *RecordingDevice::getName() const const char *RecordingDevice::getName() const
+2 -2
View File
@@ -9,7 +9,7 @@
* including commercial applications, and to alter it and redistribute it * including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions: * freely, subject to the following restrictions:
* *
* 1. The origin of this software must not be misrepresented = 0; you must not * 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 * claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be * in a product, an acknowledgment in the product documentation would be
* appreciated but is not required. * appreciated but is not required.
@@ -36,11 +36,11 @@ class RecordingDevice : public love::audio::RecordingDevice
public: public:
RecordingDevice(const char *name); RecordingDevice(const char *name);
virtual ~RecordingDevice(); virtual ~RecordingDevice();
virtual bool start();
virtual bool start(int samples, int sampleRate, int bitDepth, int channels); virtual bool start(int samples, int sampleRate, int bitDepth, int channels);
virtual void stop(); virtual void stop();
virtual love::sound::SoundData *getData(); virtual love::sound::SoundData *getData();
virtual const char *getName() const; virtual const char *getName() const;
virtual int getMaxSamples() const;
virtual int getSampleCount() const; virtual int getSampleCount() const;
virtual int getSampleRate() const; virtual int getSampleRate() const;
virtual int getBitDepth() const; virtual int getBitDepth() const;
+1 -1
View File
@@ -274,7 +274,7 @@ bool Source::getEffect(const char *, std::map<Filter::Parameter, float> &)
return false; return false;
} }
bool Source::getEffectsList(std::vector<std::string> &) bool Source::getActiveEffects(std::vector<std::string> &) const
{ {
return false; return false;
} }
+1 -1
View File
@@ -90,7 +90,7 @@ public:
virtual bool setEffect(const char *effect, const std::map<Filter::Parameter, float> &params); virtual bool setEffect(const char *effect, const std::map<Filter::Parameter, float> &params);
virtual bool unsetEffect(const char *effect); virtual bool unsetEffect(const char *effect);
virtual bool getEffect(const char *effect, std::map<Filter::Parameter, float> &params); virtual bool getEffect(const char *effect, std::map<Filter::Parameter, float> &params);
virtual bool getEffectsList(std::vector<std::string> &list); virtual bool getActiveEffects(std::vector<std::string> &list) const;
private: private:
+1 -1
View File
@@ -543,7 +543,7 @@ bool Audio::getEffect(const char *name, std::map<Effect::Parameter, float> &para
return true; return true;
} }
bool Audio::getEffectsList(std::vector<std::string> &list) bool Audio::getActiveEffects(std::vector<std::string> &list) const
{ {
if (effectmap.empty()) if (effectmap.empty())
return false; return false;
+1 -1
View File
@@ -118,7 +118,7 @@ public:
bool setEffect(const char *name, std::map<Effect::Parameter, float> &params); bool setEffect(const char *name, std::map<Effect::Parameter, float> &params);
bool unsetEffect(const char *name); bool unsetEffect(const char *name);
bool getEffect(const char *name, std::map<Effect::Parameter, float> &params); bool getEffect(const char *name, std::map<Effect::Parameter, float> &params);
bool getEffectsList(std::vector<std::string> &list); bool getActiveEffects(std::vector<std::string> &list) const;
int getMaxSceneEffects() const; int getMaxSceneEffects() const;
int getMaxSourceEffects() const; int getMaxSourceEffects() const;
bool isEFXsupported() const; bool isEFXsupported() const;
+12 -17
View File
@@ -9,7 +9,7 @@
* including commercial applications, and to alter it and redistribute it * including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions: * freely, subject to the following restrictions:
* *
* 1. The origin of this software must not be misrepresented = 0; you must not * 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 * claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be * in a product, an acknowledgment in the product documentation would be
* appreciated but is not required. * appreciated but is not required.
@@ -49,26 +49,11 @@ RecordingDevice::RecordingDevice(const char *name)
RecordingDevice::~RecordingDevice() RecordingDevice::~RecordingDevice()
{ {
if (!isRecording()) stop();
return;
alcCaptureStop(device);
alcCaptureCloseDevice(device);
}
bool RecordingDevice::start()
{
return start(samples, sampleRate, bitDepth, channels);
} }
bool RecordingDevice::start(int samples, int sampleRate, int bitDepth, int channels) bool RecordingDevice::start(int samples, int sampleRate, int bitDepth, int channels)
{ {
if (isRecording())
{
alcCaptureStop(device);
alcCaptureCloseDevice(device);
}
ALenum format = Audio::getFormat(bitDepth, channels); ALenum format = Audio::getFormat(bitDepth, channels);
if (format == AL_NONE) if (format == AL_NONE)
throw InvalidFormatException(channels, bitDepth); throw InvalidFormatException(channels, bitDepth);
@@ -79,15 +64,20 @@ bool RecordingDevice::start(int samples, int sampleRate, int bitDepth, int chann
if (sampleRate <= 0) if (sampleRate <= 0)
throw love::Exception("Invalid sample rate."); throw love::Exception("Invalid sample rate.");
if (isRecording())
stop();
device = alcCaptureOpenDevice(name.c_str(), sampleRate, format, samples); device = alcCaptureOpenDevice(name.c_str(), sampleRate, format, samples);
if (device == nullptr) if (device == nullptr)
return false; return false;
alcCaptureStart(device); alcCaptureStart(device);
this->samples = samples; this->samples = samples;
this->sampleRate = sampleRate; this->sampleRate = sampleRate;
this->bitDepth = bitDepth; this->bitDepth = bitDepth;
this->channels = channels; this->channels = channels;
return true; return true;
} }
@@ -127,6 +117,11 @@ int RecordingDevice::getSampleCount() const
return (int)samples; return (int)samples;
} }
int RecordingDevice::getMaxSamples() const
{
return samples;
}
int RecordingDevice::getSampleRate() const int RecordingDevice::getSampleRate() const
{ {
return sampleRate; return sampleRate;
+10 -6
View File
@@ -9,7 +9,7 @@
* including commercial applications, and to alter it and redistribute it * including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions: * freely, subject to the following restrictions:
* *
* 1. The origin of this software must not be misrepresented = 0; you must not * 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 * claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be * in a product, an acknowledgment in the product documentation would be
* appreciated but is not required. * appreciated but is not required.
@@ -49,26 +49,30 @@ namespace openal
class RecordingDevice : public love::audio::RecordingDevice class RecordingDevice : public love::audio::RecordingDevice
{ {
public: public:
RecordingDevice(const char *name); RecordingDevice(const char *name);
virtual ~RecordingDevice(); virtual ~RecordingDevice();
virtual bool start();
virtual bool start(int samples, int sampleRate, int bitDepth, int channels); virtual bool start(int samples, int sampleRate, int bitDepth, int channels);
virtual void stop(); virtual void stop();
virtual love::sound::SoundData *getData(); virtual love::sound::SoundData *getData();
virtual const char *getName() const; virtual const char *getName() const;
virtual int getSampleCount() const; virtual int getSampleCount() const;
virtual int getMaxSamples() const;
virtual int getSampleRate() const; virtual int getSampleRate() const;
virtual int getBitDepth() const; virtual int getBitDepth() const;
virtual int getChannels() const; virtual int getChannels() const;
virtual bool isRecording() const; virtual bool isRecording() const;
private: private:
int samples = 8192;
int sampleRate = 8000; int samples = DEFAULT_SAMPLES;
int bitDepth = 16; int sampleRate = DEFAULT_SAMPLE_RATE;
int channels = 1; int bitDepth = DEFAULT_BIT_DEPTH;
int channels = DEFAULT_CHANNELS;
std::string name; std::string name;
ALCdevice *device = nullptr; ALCdevice *device = nullptr;
}; //RecordingDevice }; //RecordingDevice
} //openal } //openal
+3 -3
View File
@@ -1041,7 +1041,7 @@ void Source::stop(const std::vector<love::audio::Source*> &sources)
sourceIds.push_back(source->source); sourceIds.push_back(source->source);
} }
alSourceStopv((ALsizei) sources.size(), &sourceIds[0]); alSourceStopv((ALsizei) sourceIds.size(), &sourceIds[0]);
for (auto &_source : sources) for (auto &_source : sources)
{ {
@@ -1068,7 +1068,7 @@ void Source::pause(const std::vector<love::audio::Source*> &sources)
sourceIds.push_back(source->source); sourceIds.push_back(source->source);
} }
alSourcePausev((ALsizei) sources.size(), &sourceIds[0]); alSourcePausev((ALsizei) sourceIds.size(), &sourceIds[0]);
} }
std::vector<love::audio::Source*> Source::pause(Pool *pool) std::vector<love::audio::Source*> Source::pause(Pool *pool)
@@ -1488,7 +1488,7 @@ bool Source::getEffect(const char *name, std::map<Filter::Parameter, float> &par
return true; return true;
} }
bool Source::getEffectsList(std::vector<std::string> &list) bool Source::getActiveEffects(std::vector<std::string> &list) const
{ {
if (effectmap.empty()) if (effectmap.empty())
return false; return false;
+1 -1
View File
@@ -152,7 +152,7 @@ public:
virtual bool setEffect(const char *effect, const std::map<Filter::Parameter, float> &params); virtual bool setEffect(const char *effect, const std::map<Filter::Parameter, float> &params);
virtual bool unsetEffect(const char *effect); virtual bool unsetEffect(const char *effect);
virtual bool getEffect(const char *effect, std::map<Filter::Parameter, float> &params); virtual bool getEffect(const char *effect, std::map<Filter::Parameter, float> &params);
virtual bool getEffectsList(std::vector<std::string> &list); virtual bool getActiveEffects(std::vector<std::string> &list) const;
virtual int getFreeBufferCount() const; virtual int getFreeBufferCount() const;
virtual bool queue(void *data, size_t length, int dataSampleRate, int dataBitDepth, int dataChannels); virtual bool queue(void *data, size_t length, int dataSampleRate, int dataBitDepth, int dataChannels);
+39 -11
View File
@@ -84,7 +84,7 @@ int w_newQueueableSource(lua_State *L)
Source *t = nullptr; Source *t = nullptr;
luax_catchexcept(L, [&]() { luax_catchexcept(L, [&]() {
t = instance()->newSource((int)luaL_checknumber(L, 1), (int)luaL_checknumber(L, 2), (int)luaL_checknumber(L, 3), (int)luaL_optnumber(L, 4, 0)); t = instance()->newSource((int)luaL_checkinteger(L, 1), (int)luaL_checkinteger(L, 2), (int)luaL_checkinteger(L, 3), (int)luaL_optinteger(L, 4, 0));
}); });
if (t != nullptr) if (t != nullptr)
@@ -115,16 +115,34 @@ static std::vector<Source*> readSourceList(lua_State *L, int n)
return sources; return sources;
} }
static std::vector<Source*> readSourceVararg(lua_State *L, int i)
{
const int top = lua_gettop(L);
if (i < 0)
i += top + 1;
int items = top - i + 1;
std::vector<Source*> sources(items);
for (int pos = 0; i <= top; i++, pos++)
sources[pos] = luax_checksource(L, i);
return sources;
}
int w_play(lua_State *L) int w_play(lua_State *L)
{ {
if (lua_istable(L, 1)) if (lua_istable(L, 1))
{
luax_pushboolean(L, instance()->play(readSourceList(L, 1))); luax_pushboolean(L, instance()->play(readSourceList(L, 1)));
return 1; else if (lua_gettop(L) > 1)
luax_pushboolean(L, instance()->play(readSourceVararg(L, 1)));
else
{
Source *s = luax_checksource(L, 1);
luax_pushboolean(L, instance()->play(s));
} }
Source *s = luax_checksource(L, 1);
luax_pushboolean(L, instance()->play(s));
return 1; return 1;
} }
@@ -134,6 +152,8 @@ int w_stop(lua_State *L)
instance()->stop(); instance()->stop();
else if (lua_istable(L, 1)) else if (lua_istable(L, 1))
instance()->stop(readSourceList(L, 1)); instance()->stop(readSourceList(L, 1));
else if (lua_gettop(L) > 1)
instance()->stop(readSourceVararg(L, 1));
else else
{ {
Source *s = luax_checksource(L, 1); Source *s = luax_checksource(L, 1);
@@ -158,6 +178,8 @@ int w_pause(lua_State *L)
} }
else if (lua_istable(L, 1)) else if (lua_istable(L, 1))
instance()->pause(readSourceList(L, 1)); instance()->pause(readSourceList(L, 1));
else if (lua_gettop(L) > 1)
instance()->pause(readSourceVararg(L, 1));
else else
{ {
Source *s = luax_checksource(L, 1); Source *s = luax_checksource(L, 1);
@@ -463,14 +485,13 @@ int w_getEffect(lua_State *L)
return 1; return 1;
} }
int w_getEffectsList(lua_State *L) int w_getActiveEffects(lua_State *L)
{ {
std::vector<std::string> list; std::vector<std::string> list;
if (!instance()->getEffectsList(list)) instance()->getActiveEffects(list);
return 0;
lua_createtable(L, 0, list.size()); lua_createtable(L, 0, (int) list.size());
for (unsigned int i = 0; i < list.size(); i++) for (int i = 0; i < (int) list.size(); i++)
{ {
lua_pushnumber(L, i + 1); lua_pushnumber(L, i + 1);
lua_pushstring(L, list[i].c_str()); lua_pushstring(L, list[i].c_str());
@@ -497,6 +518,12 @@ int w_isEffectsSupported(lua_State *L)
return 1; return 1;
} }
int w_setMixWithSystem(lua_State *L)
{
luax_pushboolean(L, instance()->setMixWithSystem(luax_toboolean(L, 1)));
return 1;
}
// List of functions to wrap. // List of functions to wrap.
static const luaL_Reg functions[] = static const luaL_Reg functions[] =
{ {
@@ -523,10 +550,11 @@ static const luaL_Reg functions[] =
{ "getRecordingDevices", w_getRecordingDevices }, { "getRecordingDevices", w_getRecordingDevices },
{ "setEffect", w_setEffect }, { "setEffect", w_setEffect },
{ "getEffect", w_getEffect }, { "getEffect", w_getEffect },
{ "getEffectsList", w_getEffectsList }, { "getActiveEffects", w_getActiveEffects },
{ "getMaxSceneEffects", w_getMaxSceneEffects }, { "getMaxSceneEffects", w_getMaxSceneEffects },
{ "getMaxSourceEffects", w_getMaxSourceEffects }, { "getMaxSourceEffects", w_getMaxSourceEffects },
{ "isEffectsSupported", w_isEffectsSupported }, { "isEffectsSupported", w_isEffectsSupported },
{ "setMixWithSystem", w_setMixWithSystem },
{ 0, 0 } { 0, 0 }
}; };
+14 -9
View File
@@ -35,19 +35,24 @@ RecordingDevice *luax_checkrecordingdevice(lua_State *L, int idx)
int w_RecordingDevice_start(lua_State *L) int w_RecordingDevice_start(lua_State *L)
{ {
RecordingDevice *d = luax_checkrecordingdevice(L, 1); RecordingDevice *d = luax_checkrecordingdevice(L, 1);
int samples = d->getMaxSamples();
int samplerate = d->getSampleRate();
int bitdepth = d->getBitDepth();
int channels = d->getChannels();
if (lua_gettop(L) > 1) if (lua_gettop(L) > 1)
{ {
int samples = (int) luaL_checkinteger(L, 2); samples = (int) luaL_checkinteger(L, 2);
int sampleRate = (int) luaL_checkinteger(L, 3); samplerate = (int) luaL_optinteger(L, 3, RecordingDevice::DEFAULT_SAMPLE_RATE);
int bitDepth = (int) luaL_checkinteger(L, 4); bitdepth = (int) luaL_optinteger(L, 4, RecordingDevice::DEFAULT_BIT_DEPTH);
int channels = (int) luaL_checkinteger(L, 5); channels = (int) (int) luaL_optinteger(L, 5, RecordingDevice::DEFAULT_CHANNELS);
luax_catchexcept(L, [&](){
lua_pushboolean(L, d->start(samples, sampleRate, bitDepth, channels));
});
} }
else
luax_catchexcept(L, [&](){ lua_pushboolean(L, d->start()); });
bool success = false;
luax_catchexcept(L, [&]() { success = d->start(samples, samplerate, bitdepth, channels); });
luax_pushboolean(L, success);
return 1; return 1;
} }
+7 -7
View File
@@ -493,15 +493,15 @@ int w_Source_getEffect(lua_State *L)
return 1; return 1;
} }
int w_Source_getEffectsList(lua_State *L) int w_Source_getActiveEffects(lua_State *L)
{ {
Source *t = luax_checksource(L, 1); Source *t = luax_checksource(L, 1);
std::vector<std::string> list;
if (!t->getEffectsList(list))
return 0;
lua_createtable(L, 0, list.size()); std::vector<std::string> list;
for (unsigned int i = 0; i < list.size(); i++) t->getActiveEffects(list);
lua_createtable(L, 0, (int) list.size());
for (int i = 0; i < (int) list.size(); i++)
{ {
lua_pushnumber(L, i + 1); lua_pushnumber(L, i + 1);
lua_pushstring(L, list[i].c_str()); lua_pushstring(L, list[i].c_str());
@@ -624,7 +624,7 @@ static const luaL_Reg w_Source_functions[] =
{ "getFilter", w_Source_getFilter }, { "getFilter", w_Source_getFilter },
{ "setEffect", w_Source_setEffect }, { "setEffect", w_Source_setEffect },
{ "getEffect", w_Source_getEffect }, { "getEffect", w_Source_getEffect },
{ "getEffectsList", w_Source_getEffectsList }, { "getActiveEffects", w_Source_getActiveEffects },
{ "getFreeBufferCount", w_Source_getFreeBufferCount }, { "getFreeBufferCount", w_Source_getFreeBufferCount },
{ "queue", w_Source_queue }, { "queue", w_Source_queue },
+6 -7
View File
@@ -65,7 +65,7 @@ bool File::open(Mode mode)
throw love::Exception("Could not open file %s. Does not exist.", filename.c_str()); throw love::Exception("Could not open file %s. Does not exist.", filename.c_str());
// Check whether the write directory is set. // Check whether the write directory is set.
if ((mode == MODE_APPEND || mode == MODE_WRITE) && (PHYSFS_getWriteDir() == 0) && !hack_setupWriteDirectory()) if ((mode == MODE_APPEND || mode == MODE_WRITE) && (PHYSFS_getWriteDir() == nullptr) && !hack_setupWriteDirectory())
throw love::Exception("Could not set write directory."); throw love::Exception("Could not set write directory.");
// File already open? // File already open?
@@ -151,8 +151,6 @@ int64 File::read(void *dst, int64 size)
int64 max = (int64)PHYSFS_fileLength(file); int64 max = (int64)PHYSFS_fileLength(file);
size = (size == ALL) ? max : size; size = (size == ALL) ? max : size;
size = (size > max) ? max : size; size = (size > max) ? max : size;
// Sadly, we'll have to clamp to 32 bits here
size = (size > LOVE_UINT32_MAX) ? LOVE_UINT32_MAX : size;
if (size < 0) if (size < 0)
throw love::Exception("Invalid read size."); throw love::Exception("Invalid read size.");
@@ -160,6 +158,8 @@ int64 File::read(void *dst, int64 size)
#ifdef LOVE_USE_PHYSFS_2_1 #ifdef LOVE_USE_PHYSFS_2_1
int64 read = PHYSFS_readBytes(file, dst, (PHYSFS_uint64) size); int64 read = PHYSFS_readBytes(file, dst, (PHYSFS_uint64) size);
#else #else
// Sadly, we'll have to clamp to 32 bits here
size = (size > LOVE_UINT32_MAX) ? LOVE_UINT32_MAX : size;
int64 read = (int64)PHYSFS_read(file, dst, 1, (PHYSFS_uint32) size); int64 read = (int64)PHYSFS_read(file, dst, 1, (PHYSFS_uint32) size);
#endif #endif
@@ -171,9 +171,6 @@ bool File::write(const void *data, int64 size)
if (!file || (mode != MODE_WRITE && mode != MODE_APPEND)) if (!file || (mode != MODE_WRITE && mode != MODE_APPEND))
throw love::Exception("File is not opened for writing."); throw love::Exception("File is not opened for writing.");
// Another clamp, for the time being.
size = (size > LOVE_UINT32_MAX) ? LOVE_UINT32_MAX : size;
if (size < 0) if (size < 0)
throw love::Exception("Invalid write size."); throw love::Exception("Invalid write size.");
@@ -181,6 +178,8 @@ bool File::write(const void *data, int64 size)
#ifdef LOVE_USE_PHYSFS_2_1 #ifdef LOVE_USE_PHYSFS_2_1
int64 written = PHYSFS_writeBytes(file, data, (PHYSFS_uint64) size); int64 written = PHYSFS_writeBytes(file, data, (PHYSFS_uint64) size);
#else #else
// Another clamp, for the time being.
size = (size > LOVE_UINT32_MAX) ? LOVE_UINT32_MAX : size;
int64 written = (int64) PHYSFS_write(file, data, 1, (PHYSFS_uint32) size); int64 written = (int64) PHYSFS_write(file, data, 1, (PHYSFS_uint32) size);
#endif #endif
@@ -191,7 +190,7 @@ bool File::write(const void *data, int64 size)
// Manually flush the buffer in BUFFER_LINE mode if we find a newline. // Manually flush the buffer in BUFFER_LINE mode if we find a newline.
if (bufferMode == BUFFER_LINE && bufferSize > size) if (bufferMode == BUFFER_LINE && bufferSize > size)
{ {
if (memchr(data, '\n', (size_t) size) != NULL) if (memchr(data, '\n', (size_t) size) != nullptr)
flush(); flush();
} }
+49 -29
View File
@@ -366,7 +366,7 @@ int w_read(lua_State *L)
const char *filename = luaL_checkstring(L, 1); const char *filename = luaL_checkstring(L, 1);
int64 len = (int64) luaL_optinteger(L, 2, File::ALL); int64 len = (int64) luaL_optinteger(L, 2, File::ALL);
Data *data = 0; Data *data = nullptr;
try try
{ {
data = instance()->read(filename, len); data = instance()->read(filename, len);
@@ -376,7 +376,7 @@ int w_read(lua_State *L)
return luax_ioError(L, "%s", e.what()); return luax_ioError(L, "%s", e.what());
} }
if (data == 0) if (data == nullptr)
return luax_ioError(L, "File could not be read."); return luax_ioError(L, "File could not be read.");
// Push the string. // Push the string.
@@ -395,7 +395,7 @@ static int w_write_or_append(lua_State *L, File::Mode mode)
{ {
const char *filename = luaL_checkstring(L, 1); const char *filename = luaL_checkstring(L, 1);
const char *input = 0; const char *input = nullptr;
size_t len = 0; size_t len = 0;
if (luax_istype(L, 2, love::Data::type)) if (luax_istype(L, 2, love::Data::type))
@@ -459,11 +459,9 @@ int w_getDirectoryItems(lua_State *L)
int w_lines(lua_State *L) int w_lines(lua_State *L)
{ {
File *file;
if (lua_isstring(L, 1)) if (lua_isstring(L, 1))
{ {
file = instance()->newFile(lua_tostring(L, 1)); File *file = instance()->newFile(lua_tostring(L, 1));
bool success = false; bool success = false;
luax_catchexcept(L, [&](){ success = file->open(File::MODE_READ); }); luax_catchexcept(L, [&](){ success = file->open(File::MODE_READ); });
@@ -488,7 +486,7 @@ int w_load(lua_State *L)
{ {
std::string filename = std::string(luaL_checkstring(L, 1)); std::string filename = std::string(luaL_checkstring(L, 1));
Data *data = 0; Data *data = nullptr;
try try
{ {
data = instance()->read(filename.c_str()); data = instance()->read(filename.c_str());
@@ -634,6 +632,22 @@ int w_setCRequirePath(lua_State *L)
return 0; return 0;
} }
static void replaceAll(std::string &str, const std::string &substr, const std::string &replacement)
{
std::vector<size_t> locations;
size_t pos = 0;
size_t sublen = substr.length();
while ((pos = str.find(substr, pos)) != std::string::npos)
{
locations.push_back(pos);
pos += sublen;
}
for (int i = (int) locations.size() - 1; i >= 0; i--)
str.replace(locations[i], sublen, replacement);
}
int loader(lua_State *L) int loader(lua_State *L)
{ {
std::string modulename = luax_tostring(L, 1); std::string modulename = luax_tostring(L, 1);
@@ -647,9 +661,7 @@ int loader(lua_State *L)
auto *inst = instance(); auto *inst = instance();
for (std::string element : inst->getRequirePath()) for (std::string element : inst->getRequirePath())
{ {
size_t pos = 0; replaceAll(element, "?", modulename);
while ((pos = element.find('?', pos)) != std::string::npos)
element.replace(pos, 1, modulename);
if (inst->isFile(element.c_str())) if (inst->isFile(element.c_str()))
{ {
@@ -665,14 +677,16 @@ int loader(lua_State *L)
return 1; return 1;
} }
inline const char *library_extension() static const char *library_extensions[] =
{ {
#ifdef LOVE_WINDOWS #ifdef LOVE_WINDOWS
return ".dll"; ".dll"
#elif defined(LOVE_MACOSX) || defined(LOVE_IOS)
".dylib", ".so"
#else #else
return ".so"; ".so"
#endif #endif
} };
int extloader(lua_State *L) int extloader(lua_State *L)
{ {
@@ -694,25 +708,31 @@ int extloader(lua_State *L)
void *handle = nullptr; void *handle = nullptr;
auto *inst = instance(); auto *inst = instance();
for (std::string element : inst->getCRequirePath())
for (const std::string &el : inst->getCRequirePath())
{ {
// Replace ?? with the filename and extension for (const char *ext : library_extensions)
size_t pos = element.find("??"); {
if (pos != std::string::npos) std::string element = el;
element.replace(pos, 2, tokenized_name + library_extension());
// Or ? with just the filename
pos = element.find('?');
if (pos != std::string::npos)
element.replace(pos, 1, tokenized_name);
if (!inst->isFile(element.c_str())) // Replace ?? with the filename and extension
continue; replaceAll(element, "??", tokenized_name + ext);
// Now resolve the full path, as we're bypassing physfs for the next part. // And ? with just the filename
element = inst->getRealDirectory(element.c_str()) + LOVE_PATH_SEPARATOR + element; replaceAll(element, "?", tokenized_name);
if (!inst->isFile(element.c_str()))
continue;
// Now resolve the full path, as we're bypassing physfs for the next part.
std::string filepath = inst->getRealDirectory(element.c_str()) + LOVE_PATH_SEPARATOR + element;
handle = SDL_LoadObject(filepath.c_str());
// Can fail, for instance if it turned out the source was a zip
if (handle)
break;
}
handle = SDL_LoadObject(element.c_str());
// Can fail, for instance if it turned out the source was a zip
if (handle) if (handle)
break; break;
} }
+11 -9
View File
@@ -146,7 +146,12 @@ BMFontRasterizer::BMFontRasterizer(love::filesystem::FileData *fontdef, const st
// The parseConfig function will try to load any missing page images. // The parseConfig function will try to load any missing page images.
for (int i = 0; i < (int) imagelist.size(); i++) for (int i = 0; i < (int) imagelist.size(); i++)
{
if (imagelist[i]->getFormat() != PIXELFORMAT_RGBA8)
throw love::Exception("Only 32-bit RGBA images are supported in BMFonts.");
images[i] = imagelist[i]; images[i] = imagelist[i];
}
std::string configtext((const char *) fontdef->getData(), fontdef->getSize()); std::string configtext((const char *) fontdef->getData(), fontdef->getSize());
@@ -296,29 +301,26 @@ GlyphData *BMFontRasterizer::getGlyphData(uint32 glyph) const
return new GlyphData(glyph, GlyphMetrics(), PIXELFORMAT_RGBA8); return new GlyphData(glyph, GlyphMetrics(), PIXELFORMAT_RGBA8);
const BMFontCharacter &c = it->second; const BMFontCharacter &c = it->second;
GlyphData *g = new GlyphData(glyph, c.metrics, PIXELFORMAT_RGBA8);
const auto &imagepair = images.find(c.page); const auto &imagepair = images.find(c.page);
if (imagepair == images.end()) if (imagepair == images.end())
{
g->release();
return new GlyphData(glyph, GlyphMetrics(), PIXELFORMAT_RGBA8); return new GlyphData(glyph, GlyphMetrics(), PIXELFORMAT_RGBA8);
}
image::ImageData *imagedata = imagepair->second.get(); image::ImageData *imagedata = imagepair->second.get();
GlyphData *g = new GlyphData(glyph, c.metrics, PIXELFORMAT_RGBA8);
size_t pixelsize = imagedata->getPixelSize(); size_t pixelsize = imagedata->getPixelSize();
image::pixel *pixels = (image::pixel *) g->getData();
const image::pixel *ipixels = (const image::pixel *) imagedata->getData(); uint8 *pixels = (uint8 *) g->getData();
const uint8 *ipixels = (const uint8 *) imagedata->getData();
love::thread::Lock lock(imagedata->getMutex()); love::thread::Lock lock(imagedata->getMutex());
// Copy the subsection of the texture from the ImageData to the GlyphData. // Copy the subsection of the texture from the ImageData to the GlyphData.
for (int y = 0; y < c.metrics.height; y++) for (int y = 0; y < c.metrics.height; y++)
{ {
size_t idindex = (c.y + y) * imagedata->getWidth() + c.x; size_t idindex = ((c.y + y) * imagedata->getWidth() + c.x) * pixelsize;
memcpy(&pixels[y * c.metrics.width], &ipixels[idindex], pixelsize * c.metrics.width); memcpy(&pixels[y * c.metrics.width * pixelsize], &ipixels[idindex], pixelsize * c.metrics.width);
} }
return g; return g;
+9 -12
View File
@@ -29,10 +29,7 @@ namespace love
namespace font namespace font
{ {
inline bool equal(const love::image::pixel &a, const love::image::pixel &b) static_assert(sizeof(Color) == 4, "sizeof(Color) must equal 4 bytes!");
{
return (a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a);
}
ImageRasterizer::ImageRasterizer(love::image::ImageData *data, uint32 *glyphs, int numglyphs, int extraspacing, float pixeldensity) ImageRasterizer::ImageRasterizer(love::image::ImageData *data, uint32 *glyphs, int numglyphs, int extraspacing, float pixeldensity)
: imageData(data) : imageData(data)
@@ -79,17 +76,17 @@ GlyphData *ImageRasterizer::getGlyphData(uint32 glyph) const
// We don't want another thread modifying our ImageData mid-copy. // We don't want another thread modifying our ImageData mid-copy.
love::thread::Lock lock(imageData->getMutex()); love::thread::Lock lock(imageData->getMutex());
love::image::pixel *gdpixels = (love::image::pixel *) g->getData(); Color *gdpixels = (Color *) g->getData();
love::image::pixel *imagepixels = (love::image::pixel *) imageData->getData(); const Color *imagepixels = (const Color *) imageData->getData();
// copy glyph pixels from imagedata to glyphdata // copy glyph pixels from imagedata to glyphdata
for (int i = 0; i < g->getWidth() * g->getHeight(); i++) for (int i = 0; i < g->getWidth() * g->getHeight(); i++)
{ {
love::image::pixel p = imagepixels[it->second.x + (i % gm.width) + (imageData->getWidth() * (i / gm.width))]; Color p = imagepixels[it->second.x + (i % gm.width) + (imageData->getWidth() * (i / gm.width))];
// Use transparency instead of the spacer color // Use transparency instead of the spacer color
if (equal(p, spacer)) if (p == spacer)
gdpixels[i].r = gdpixels[i].g = gdpixels[i].b = gdpixels[i].a = 0; gdpixels[i] = Color(0, 0, 0, 0);
else else
gdpixels[i] = p; gdpixels[i] = p;
} }
@@ -99,7 +96,7 @@ GlyphData *ImageRasterizer::getGlyphData(uint32 glyph) const
void ImageRasterizer::load() void ImageRasterizer::load()
{ {
love::image::pixel *pixels = (love::image::pixel *) imageData->getData(); const Color *pixels = (const Color *) imageData->getData();
int imgw = imageData->getWidth(); int imgw = imageData->getWidth();
int imgh = imageData->getHeight(); int imgh = imageData->getHeight();
@@ -121,13 +118,13 @@ void ImageRasterizer::load()
start = end; start = end;
// Finds out where the first character starts // Finds out where the first character starts
while (start < imgw && equal(pixels[start], spacer)) while (start < imgw && pixels[start] == spacer)
++start; ++start;
end = start; end = start;
// Find where glyph ends. // Find where glyph ends.
while (end < imgw && !equal(pixels[end], spacer)) while (end < imgw && pixels[end] != spacer)
++end; ++end;
if (start >= end) if (start >= end)
+2 -2
View File
@@ -22,9 +22,9 @@
#define LOVE_FONT_IMAGE_RASTERIZER_H #define LOVE_FONT_IMAGE_RASTERIZER_H
// LOVE // LOVE
#include "filesystem/File.h"
#include "font/Rasterizer.h" #include "font/Rasterizer.h"
#include "image/ImageData.h" #include "image/ImageData.h"
#include "common/Color.h"
#include <map> #include <map>
@@ -76,7 +76,7 @@ private:
std::map<uint32, ImageGlyphData> imageGlyphs; std::map<uint32, ImageGlyphData> imageGlyphs;
// Color used to identify glyph separation in the source ImageData // Color used to identify glyph separation in the source ImageData
love::image::pixel spacer; Color spacer;
}; // ImageRasterizer }; // ImageRasterizer
+3 -3
View File
@@ -72,7 +72,7 @@ int w_newTrueTypeRasterizer(lua_State *L)
if (lua_type(L, 1) == LUA_TNUMBER || lua_isnone(L, 1)) if (lua_type(L, 1) == LUA_TNUMBER || lua_isnone(L, 1))
{ {
// First argument is a number: use the default TrueType font. // First argument is a number: use the default TrueType font.
int size = (int) luaL_optnumber(L, 1, 12); int size = (int) luaL_optinteger(L, 1, 12);
const char *hintstr = lua_isnoneornil(L, 2) ? nullptr : luaL_checkstring(L, 2); const char *hintstr = lua_isnoneornil(L, 2) ? nullptr : luaL_checkstring(L, 2);
if (hintstr && !TrueTypeRasterizer::getConstant(hintstr, hinting)) if (hintstr && !TrueTypeRasterizer::getConstant(hintstr, hinting))
@@ -98,7 +98,7 @@ int w_newTrueTypeRasterizer(lua_State *L)
else else
d = filesystem::luax_getfiledata(L, 1); d = filesystem::luax_getfiledata(L, 1);
int size = (int) luaL_optnumber(L, 2, 12); int size = (int) luaL_optinteger(L, 2, 12);
const char *hintstr = lua_isnoneornil(L, 3) ? nullptr : luaL_checkstring(L, 3); const char *hintstr = lua_isnoneornil(L, 3) ? nullptr : luaL_checkstring(L, 3);
if (hintstr && !TrueTypeRasterizer::getConstant(hintstr, hinting)) if (hintstr && !TrueTypeRasterizer::getConstant(hintstr, hinting))
@@ -180,7 +180,7 @@ int w_newImageRasterizer(lua_State *L)
image::ImageData *d = luax_checktype<image::ImageData>(L, 1); image::ImageData *d = luax_checktype<image::ImageData>(L, 1);
std::string glyphs = luax_checkstring(L, 2); std::string glyphs = luax_checkstring(L, 2);
int extraspacing = (int) luaL_optnumber(L, 3, 0); int extraspacing = (int) luaL_optinteger(L, 3, 0);
float pixeldensity = (float) luaL_optnumber(L, 4, 1.0); float pixeldensity = (float) luaL_optnumber(L, 4, 1.0);
luax_catchexcept(L, [&](){ t = instance()->newImageRasterizer(d, glyphs, extraspacing, pixeldensity); }); luax_catchexcept(L, [&](){ t = instance()->newImageRasterizer(d, glyphs, extraspacing, pixeldensity); });
+1 -1
View File
@@ -151,7 +151,7 @@ IndexDataType QuadIndices::getType(size_t s) const
return vertex::getIndexDataTypeFromMax(getIndexCount(s)); return vertex::getIndexDataTypeFromMax(getIndexCount(s));
} }
size_t QuadIndices::getElementSize() size_t QuadIndices::getElementSize() const
{ {
return elementSize; return elementSize;
} }
+1 -1
View File
@@ -238,7 +238,7 @@ public:
* Can be used with getPointer to calculate an offset into the array based * Can be used with getPointer to calculate an offset into the array based
* on a number of elements. * on a number of elements.
**/ **/
size_t getElementSize(); size_t getElementSize() const;
/** /**
* Returns the pointer to the Buffer. * Returns the pointer to the Buffer.
+1 -37
View File
@@ -97,43 +97,7 @@ Canvas::Canvas(const Settings &settings)
throw love::Exception("%s textures are not supported on this system!", textypestr); throw love::Exception("%s textures are not supported on this system!", textypestr);
} }
int maxsize = 0; validateDimensions(true);
switch (texType)
{
case TEXTURE_2D:
maxsize = (int) caps.limits[Graphics::LIMIT_TEXTURE_SIZE];
if (pixelWidth > maxsize)
throw TextureTooLargeException("width", pixelWidth);
else if (pixelHeight > maxsize)
throw TextureTooLargeException("height", pixelHeight);
break;
case TEXTURE_VOLUME:
maxsize = (int) caps.limits[Graphics::LIMIT_VOLUME_TEXTURE_SIZE];
if (pixelWidth > maxsize)
throw TextureTooLargeException("width", pixelWidth);
else if (pixelHeight > maxsize)
throw TextureTooLargeException("height", pixelHeight);
else if (depth > maxsize)
throw TextureTooLargeException("depth", depth);
break;
case TEXTURE_2D_ARRAY:
maxsize = (int) caps.limits[Graphics::LIMIT_TEXTURE_SIZE];
if (pixelWidth > maxsize)
throw TextureTooLargeException("width", pixelWidth);
else if (pixelHeight > maxsize)
throw TextureTooLargeException("height", pixelHeight);
else if (layers > (int) caps.limits[Graphics::LIMIT_TEXTURE_LAYERS])
throw TextureTooLargeException("array layer count", layers);
break;
case TEXTURE_CUBE:
if (pixelWidth != pixelHeight)
throw love::Exception("Cubemap textures must have equal width and height.");
else if (pixelWidth > (int) caps.limits[Graphics::LIMIT_CUBE_TEXTURE_SIZE])
throw TextureTooLargeException("width", pixelWidth);
break;
default:
break;
}
canvasCount++; canvasCount++;
} }
+172 -52
View File
@@ -112,6 +112,7 @@ Graphics::Graphics()
, streamBufferState() , streamBufferState()
, projectionMatrix() , projectionMatrix()
, canvasSwitchCount(0) , canvasSwitchCount(0)
, drawCallsBatched(0)
, capabilities() , capabilities()
{ {
transformStack.reserve(16); transformStack.reserve(16);
@@ -430,6 +431,128 @@ void Graphics::setCanvas(const RenderTargetsStrongRef &rts)
return setCanvas(targets); return setCanvas(targets);
} }
void Graphics::setCanvas(const RenderTargets &rts)
{
DisplayState &state = states.back();
int ncanvases = (int) rts.colors.size();
if (ncanvases == 0 && rts.depthStencil.canvas == nullptr)
return setCanvas();
else if (ncanvases == 0)
throw love::Exception("At least one color render target is required when using a custom depth/stencil buffer.");
const auto &prevRTs = state.renderTargets;
if (ncanvases == (int) prevRTs.colors.size())
{
bool modified = false;
for (int i = 0; i < ncanvases; i++)
{
if (rts.colors[i].canvas != prevRTs.colors[i].canvas.get()
|| rts.colors[i].slice != prevRTs.colors[i].slice
|| rts.colors[i].mipmap != prevRTs.colors[i].mipmap)
{
modified = true;
break;
}
}
if (!modified && (rts.depthStencil.canvas != prevRTs.depthStencil.canvas
|| rts.depthStencil.slice != prevRTs.depthStencil.slice
|| rts.depthStencil.mipmap != prevRTs.depthStencil.mipmap))
{
modified = true;
}
if (rts.temporaryRTFlags != prevRTs.temporaryRTFlags)
modified = true;
if (!modified)
return;
}
if (ncanvases > capabilities.limits[LIMIT_MULTI_CANVAS])
throw love::Exception("This system can't simultaneously render to %d canvases.", ncanvases);
love::graphics::Canvas *firstcanvas = rts.colors[0].canvas;
bool multiformatsupported = capabilities.features[FEATURE_MULTI_CANVAS_FORMATS];
PixelFormat firstformat = firstcanvas->getPixelFormat();
if (isPixelFormatDepthStencil(firstformat))
throw love::Exception("Depth/stencil format Canvases must be used with the 'depthstencil' field of the table passed into setCanvas.");
if (rts.colors[0].mipmap < 0 || rts.colors[0].mipmap >= firstcanvas->getMipmapCount())
throw love::Exception("Invalid mipmap level %d.", rts.colors[0].mipmap + 1);
bool hasSRGBcanvas = firstformat == PIXELFORMAT_sRGBA8;
int pixelw = firstcanvas->getPixelWidth(rts.colors[0].mipmap);
int pixelh = firstcanvas->getPixelHeight(rts.colors[0].mipmap);
for (int i = 1; i < ncanvases; i++)
{
love::graphics::Canvas *c = rts.colors[i].canvas;
PixelFormat format = c->getPixelFormat();
int mip = rts.colors[i].mipmap;
if (mip < 0 || mip >= c->getMipmapCount())
throw love::Exception("Invalid mipmap level %d.", mip + 1);
if (c->getPixelWidth(mip) != pixelw || c->getPixelHeight(mip) != pixelh)
throw love::Exception("All canvases must have the same pixel dimensions.");
if (!multiformatsupported && format != firstformat)
throw love::Exception("This system doesn't support multi-canvas rendering with different canvas formats.");
if (c->getRequestedMSAA() != firstcanvas->getRequestedMSAA())
throw love::Exception("All Canvases must have the same MSAA value.");
if (isPixelFormatDepthStencil(format))
throw love::Exception("Depth/stencil format Canvases must be used with the 'depthstencil' field of the table passed into setCanvas.");
if (format == PIXELFORMAT_sRGBA8)
hasSRGBcanvas = true;
}
if (rts.depthStencil.canvas != nullptr)
{
love::graphics::Canvas *c = rts.depthStencil.canvas;
int mip = rts.depthStencil.mipmap;
if (!isPixelFormatDepthStencil(c->getPixelFormat()))
throw love::Exception("Only depth/stencil format Canvases can be used with the 'depthstencil' field of the table passed into setCanvas.");
if (c->getPixelWidth(mip) != pixelw || c->getPixelHeight(mip) != pixelh)
throw love::Exception("All canvases must have the same pixel dimensions.");
if (c->getRequestedMSAA() != firstcanvas->getRequestedMSAA())
throw love::Exception("All Canvases must have the same MSAA value.");
if (mip < 0 || mip >= c->getMipmapCount())
throw love::Exception("Invalid mipmap level %d.", mip + 1);
}
int w = firstcanvas->getWidth(rts.colors[0].mipmap);
int h = firstcanvas->getHeight(rts.colors[0].mipmap);
flushStreamDraws();
setCanvasInternal(rts, w, h, pixelw, pixelh, hasSRGBcanvas);
RenderTargetsStrongRef refs;
refs.colors.reserve(rts.colors.size());
for (auto c : rts.colors)
refs.colors.emplace_back(c.canvas, c.slice);
refs.depthStencil = RenderTargetStrongRef(rts.depthStencil.canvas, rts.depthStencil.slice);
refs.temporaryRTFlags = rts.temporaryRTFlags;
std::swap(state.renderTargets, refs);
canvasSwitchCount++;
}
Graphics::RenderTargets Graphics::getCanvas() const Graphics::RenderTargets Graphics::getCanvas() const
{ {
const auto &curRTs = states.back().renderTargets; const auto &curRTs = states.back().renderTargets;
@@ -757,6 +880,9 @@ Graphics::StreamVertexData Graphics::requestStreamDraw(const StreamDrawRequest &
} }
} }
if (state.vertexCount > 0)
drawCallsBatched++;
state.vertexCount += req.vertexCount; state.vertexCount += req.vertexCount;
state.indexCount += reqIndexCount; state.indexCount += reqIndexCount;
@@ -829,7 +955,7 @@ void Graphics::printf(const std::vector<Font::ColoredString> &str, Font *font, f
* Primitives (points, shapes, lines). * Primitives (points, shapes, lines).
**/ **/
void Graphics::points(const float *coords, const Colorf *colors, size_t numpoints) void Graphics::points(const Vector2 *positions, const Colorf *colors, size_t numpoints)
{ {
const Matrix4 &t = getTransform(); const Matrix4 &t = getTransform();
bool is2D = t.isAffine2DTransform(); bool is2D = t.isAffine2DTransform();
@@ -843,9 +969,9 @@ void Graphics::points(const float *coords, const Colorf *colors, size_t numpoint
StreamVertexData data = requestStreamDraw(req); StreamVertexData data = requestStreamDraw(req);
if (is2D) if (is2D)
t.transformXY((Vector2 *) data.stream[0], (const Vector2 *) coords, req.vertexCount); t.transformXY((Vector2 *) data.stream[0], positions, req.vertexCount);
else else
t.transformXY0((Vector3 *) data.stream[0], (const Vector2 *) coords, req.vertexCount); t.transformXY0((Vector3 *) data.stream[0], positions, req.vertexCount);
Color *colordata = (Color *) data.stream[1]; Color *colordata = (Color *) data.stream[1];
@@ -886,7 +1012,7 @@ int Graphics::calculateEllipsePoints(float rx, float ry) const
return std::max(points, 8); return std::max(points, 8);
} }
void Graphics::polyline(const float *coords, size_t count) void Graphics::polyline(const Vector2 *vertices, size_t count)
{ {
float halfwidth = getLineWidth() * 0.5f; float halfwidth = getLineWidth() * 0.5f;
LineJoin linejoin = getLineJoin(); LineJoin linejoin = getLineJoin();
@@ -897,27 +1023,27 @@ void Graphics::polyline(const float *coords, size_t count)
if (linejoin == LINE_JOIN_NONE) if (linejoin == LINE_JOIN_NONE)
{ {
NoneJoinPolyline line; NoneJoinPolyline line;
line.render(coords, count, halfwidth, pixelsize, linestyle == LINE_SMOOTH); line.render(vertices, count, halfwidth, pixelsize, linestyle == LINE_SMOOTH);
line.draw(this); line.draw(this);
} }
else if (linejoin == LINE_JOIN_BEVEL) else if (linejoin == LINE_JOIN_BEVEL)
{ {
BevelJoinPolyline line; BevelJoinPolyline line;
line.render(coords, count, halfwidth, pixelsize, linestyle == LINE_SMOOTH); line.render(vertices, count, halfwidth, pixelsize, linestyle == LINE_SMOOTH);
line.draw(this); line.draw(this);
} }
else if (linejoin == LINE_JOIN_MITER) else if (linejoin == LINE_JOIN_MITER)
{ {
MiterJoinPolyline line; MiterJoinPolyline line;
line.render(coords, count, halfwidth, pixelsize, linestyle == LINE_SMOOTH); line.render(vertices, count, halfwidth, pixelsize, linestyle == LINE_SMOOTH);
line.draw(this); line.draw(this);
} }
} }
void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h) void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h)
{ {
float coords[] = {x,y, x,y+h, x+w,y+h, x+w,y, x,y}; Vector2 coords[] = {Vector2(x,y), Vector2(x,y+h), Vector2(x+w,y+h), Vector2(x+w,y), Vector2(x,y)};
polygon(mode, coords, 5 * 2); polygon(mode, coords, 5);
} }
void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h, float rx, float ry, int points) void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h, float rx, float ry, int points)
@@ -940,44 +1066,43 @@ void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h, floa
const float half_pi = static_cast<float>(LOVE_M_PI / 2); const float half_pi = static_cast<float>(LOVE_M_PI / 2);
float angle_shift = half_pi / ((float) points + 1.0f); float angle_shift = half_pi / ((float) points + 1.0f);
int num_coords = (points + 2) * 8; int num_coords = (points + 2) * 4;
float *coords = getScratchBuffer<float>(num_coords + 2); Vector2 *coords = getScratchBuffer<Vector2>(num_coords + 1);
float phi = .0f; float phi = .0f;
for (int i = 0; i <= points + 2; ++i, phi += angle_shift) for (int i = 0; i <= points + 2; ++i, phi += angle_shift)
{ {
coords[2 * i + 0] = x + rx * (1 - cosf(phi)); coords[i].x = x + rx * (1 - cosf(phi));
coords[2 * i + 1] = y + ry * (1 - sinf(phi)); coords[i].y = y + ry * (1 - sinf(phi));
} }
phi = half_pi; phi = half_pi;
for (int i = points + 2; i <= 2 * (points + 2); ++i, phi += angle_shift) for (int i = points + 2; i <= 2 * (points + 2); ++i, phi += angle_shift)
{ {
coords[2 * i + 0] = x + w - rx * (1 + cosf(phi)); coords[i].x = x + w - rx * (1 + cosf(phi));
coords[2 * i + 1] = y + ry * (1 - sinf(phi)); coords[i].y = y + ry * (1 - sinf(phi));
} }
phi = 2 * half_pi; phi = 2 * half_pi;
for (int i = 2 * (points + 2); i <= 3 * (points + 2); ++i, phi += angle_shift) for (int i = 2 * (points + 2); i <= 3 * (points + 2); ++i, phi += angle_shift)
{ {
coords[2 * i + 0] = x + w - rx * (1 + cosf(phi)); coords[i].x = x + w - rx * (1 + cosf(phi));
coords[2 * i + 1] = y + h - ry * (1 + sinf(phi)); coords[i].y = y + h - ry * (1 + sinf(phi));
} }
phi = 3 * half_pi; phi = 3 * half_pi;
for (int i = 3 * (points + 2); i <= 4 * (points + 2); ++i, phi += angle_shift) for (int i = 3 * (points + 2); i <= 4 * (points + 2); ++i, phi += angle_shift)
{ {
coords[2 * i + 0] = x + rx * (1 - cosf(phi)); coords[i].x = x + rx * (1 - cosf(phi));
coords[2 * i + 1] = y + h - ry * (1 + sinf(phi)); coords[i].y = y + h - ry * (1 + sinf(phi));
} }
coords[num_coords + 0] = coords[0]; coords[num_coords] = coords[0];
coords[num_coords + 1] = coords[1];
polygon(mode, coords, num_coords + 2); polygon(mode, coords, num_coords + 1);
} }
void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h, float rx, float ry) void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h, float rx, float ry)
@@ -1002,17 +1127,16 @@ void Graphics::ellipse(DrawMode mode, float x, float y, float a, float b, int po
float angle_shift = (two_pi / points); float angle_shift = (two_pi / points);
float phi = .0f; float phi = .0f;
float *coords = getScratchBuffer<float>(2 * (points + 1)); Vector2 *coords = getScratchBuffer<Vector2>(points + 1);
for (int i = 0; i < points; ++i, phi += angle_shift) for (int i = 0; i < points; ++i, phi += angle_shift)
{ {
coords[2*i+0] = x + a * cosf(phi); coords[i].x = x + a * cosf(phi);
coords[2*i+1] = y + b * sinf(phi); coords[i].y = y + b * sinf(phi);
} }
coords[2*points+0] = coords[0]; coords[points] = coords[0];
coords[2*points+1] = coords[1];
polygon(mode, coords, (points + 1) * 2); polygon(mode, coords, points + 1);
} }
void Graphics::ellipse(DrawMode mode, float x, float y, float a, float b) void Graphics::ellipse(DrawMode mode, float x, float y, float a, float b)
@@ -1051,45 +1175,43 @@ void Graphics::arc(DrawMode drawmode, ArcMode arcmode, float x, float y, float r
float phi = angle1; float phi = angle1;
float *coords = nullptr; Vector2 *coords = nullptr;
int num_coords = 0; int num_coords = 0;
const auto createPoints = [&](float *coordinates) const auto createPoints = [&](Vector2 *coordinates)
{ {
for (int i = 0; i <= points; ++i, phi += angle_shift) for (int i = 0; i <= points; ++i, phi += angle_shift)
{ {
coordinates[2 * i + 0] = x + radius * cosf(phi); coordinates[i].x = x + radius * cosf(phi);
coordinates[2 * i + 1] = y + radius * sinf(phi); coordinates[i].y = y + radius * sinf(phi);
} }
}; };
if (arcmode == ARC_PIE) if (arcmode == ARC_PIE)
{ {
num_coords = (points + 3) * 2; num_coords = points + 3;
coords = getScratchBuffer<float>(num_coords); coords = getScratchBuffer<Vector2>(num_coords);
coords[0] = coords[num_coords - 2] = x; coords[0] = coords[num_coords - 1] = Vector2(x, y);
coords[1] = coords[num_coords - 1] = y;
createPoints(coords + 2); createPoints(coords + 1);
} }
else if (arcmode == ARC_OPEN) else if (arcmode == ARC_OPEN)
{ {
num_coords = (points + 1) * 2; num_coords = points + 1;
coords = getScratchBuffer<float>(num_coords); coords = getScratchBuffer<Vector2>(num_coords);
createPoints(coords); createPoints(coords);
} }
else // ARC_CLOSED else // ARC_CLOSED
{ {
num_coords = (points + 2) * 2; num_coords = points + 2;
coords = getScratchBuffer<float>(num_coords); coords = getScratchBuffer<Vector2>(num_coords);
createPoints(coords); createPoints(coords);
// Connect the ends of the arc. // Connect the ends of the arc.
coords[num_coords - 2] = coords[0]; coords[num_coords - 1] = coords[0];
coords[num_coords - 1] = coords[1];
} }
polygon(drawmode, coords, num_coords); polygon(drawmode, coords, num_coords);
@@ -1107,13 +1229,10 @@ void Graphics::arc(DrawMode drawmode, ArcMode arcmode, float x, float y, float r
arc(drawmode, arcmode, x, y, radius, angle1, angle2, (int) (points + 0.5f)); arc(drawmode, arcmode, x, y, radius, angle1, angle2, (int) (points + 0.5f));
} }
/// @param mode the draw mode void Graphics::polygon(DrawMode mode, const Vector2 *coords, size_t count)
/// @param coords the coordinate array
/// @param count the number of coordinates/size of the array
void Graphics::polygon(DrawMode mode, const float *coords, size_t count)
{ {
// coords is an array of a closed loop of vertices, i.e. // coords is an array of a closed loop of vertices, i.e.
// coords[count-2] = coords[0], coords[count-1] = coords[1] // coords[count-1] == coords[0]
if (mode == DRAW_LINE) if (mode == DRAW_LINE)
{ {
polyline(coords, count); polyline(coords, count);
@@ -1127,14 +1246,14 @@ void Graphics::polygon(DrawMode mode, const float *coords, size_t count)
req.formats[0] = vertex::getSinglePositionFormat(is2D); req.formats[0] = vertex::getSinglePositionFormat(is2D);
req.formats[1] = vertex::CommonFormat::RGBAub; req.formats[1] = vertex::CommonFormat::RGBAub;
req.indexMode = vertex::TriangleIndexMode::FAN; req.indexMode = vertex::TriangleIndexMode::FAN;
req.vertexCount = (int)count/2 - 1; req.vertexCount = (int)count - 1;
StreamVertexData data = requestStreamDraw(req); StreamVertexData data = requestStreamDraw(req);
if (is2D) if (is2D)
t.transformXY((Vector2 *) data.stream[0], (const Vector2 *) coords, req.vertexCount); t.transformXY((Vector2 *) data.stream[0], coords, req.vertexCount);
else else
t.transformXY0((Vector3 *) data.stream[0], (const Vector2 *) coords, req.vertexCount); t.transformXY0((Vector3 *) data.stream[0], coords, req.vertexCount);
Color c = toColor(getColor()); Color c = toColor(getColor());
Color *colordata = (Color *) data.stream[1]; Color *colordata = (Color *) data.stream[1];
@@ -1158,6 +1277,7 @@ Graphics::Stats Graphics::getStats() const
stats.drawCalls++; stats.drawCalls++;
stats.canvasSwitches = canvasSwitchCount; stats.canvasSwitches = canvasSwitchCount;
stats.drawCallsBatched = drawCallsBatched;
stats.canvases = Canvas::canvasCount; stats.canvases = Canvas::canvasCount;
stats.images = Image::imageCount; stats.images = Image::imageCount;
stats.fonts = Font::fontCount; stats.fonts = Font::fontCount;
+14 -12
View File
@@ -28,9 +28,9 @@
#include "common/Vector.h" #include "common/Vector.h"
#include "common/Optional.h" #include "common/Optional.h"
#include "common/int.h" #include "common/int.h"
#include "common/Color.h"
#include "StreamBuffer.h" #include "StreamBuffer.h"
#include "vertex.h" #include "vertex.h"
#include "Color.h"
#include "Texture.h" #include "Texture.h"
#include "Canvas.h" #include "Canvas.h"
#include "Font.h" #include "Font.h"
@@ -216,6 +216,7 @@ public:
struct Stats struct Stats
{ {
int drawCalls; int drawCalls;
int drawCallsBatched;
int canvasSwitches; int canvasSwitches;
int shaderSwitches; int shaderSwitches;
int canvases; int canvases;
@@ -478,7 +479,7 @@ public:
Shader *getShader() const; Shader *getShader() const;
void setCanvas(RenderTarget rt, uint32 temporaryRTFlags); void setCanvas(RenderTarget rt, uint32 temporaryRTFlags);
virtual void setCanvas(const RenderTargets &rts) = 0; void setCanvas(const RenderTargets &rts);
void setCanvas(const RenderTargetsStrongRef &rts); void setCanvas(const RenderTargetsStrongRef &rts);
virtual void setCanvas() = 0; virtual void setCanvas() = 0;
@@ -620,18 +621,16 @@ public:
void printf(const std::vector<Font::ColoredString> &str, Font *font, float wrap, Font::AlignMode align, const Matrix4 &m); void printf(const std::vector<Font::ColoredString> &str, Font *font, float wrap, Font::AlignMode align, const Matrix4 &m);
/** /**
* Draws a point at (x,y). * Draws a series of points at the specified positions.
* @param x Point along x-axis.
* @param y Point along y-axis.
**/ **/
void points(const float *coords, const Colorf *colors, size_t numpoints); void points(const Vector2 *positions, const Colorf *colors, size_t numpoints);
/** /**
* Draws a series of lines connecting the given vertices. * Draws a series of lines connecting the given vertices.
* @param coords Vertex components (x1, y1, ..., xn, yn). If x1,y1 == xn,yn the line will be drawn closed. * @param coords Vertex positions (v1, ..., vn). If v1 == vn the line will be drawn closed.
* @param count Number of items in the array, i.e. count = 2 * n * @param count Number of vertices.
**/ **/
void polyline(const float *coords, size_t count); void polyline(const Vector2 *vertices, size_t count);
/** /**
* Draws a rectangle. * Draws a rectangle.
@@ -696,10 +695,10 @@ public:
/** /**
* Draws a polygon with an arbitrary number of vertices. * Draws a polygon with an arbitrary number of vertices.
* @param mode The type of drawing (line/filled). * @param mode The type of drawing (line/filled).
* @param coords Vertex components (x1, y1, x2, y2, etc.) * @param coords Vertex positions.
* @param count Coord array size * @param count Vertex array size.
**/ **/
void polygon(DrawMode mode, const float *coords, size_t count); void polygon(DrawMode mode, const Vector2 *vertices, size_t count);
/** /**
* Gets the graphics capabilities (feature support, limit values, and * Gets the graphics capabilities (feature support, limit values, and
@@ -861,6 +860,8 @@ protected:
virtual StreamBuffer *newStreamBuffer(BufferType type, size_t size) = 0; virtual StreamBuffer *newStreamBuffer(BufferType type, size_t size) = 0;
virtual void setCanvasInternal(const RenderTargets &rts, int w, int h, int pixelw, int pixelh, bool hasSRGBcanvas) = 0;
virtual void initCapabilities() = 0; virtual void initCapabilities() = 0;
virtual void getAPIStats(int &drawcalls, int &shaderswitches) const = 0; virtual void getAPIStats(int &drawcalls, int &shaderswitches) const = 0;
@@ -900,6 +901,7 @@ protected:
std::vector<Canvas *> temporaryCanvases; std::vector<Canvas *> temporaryCanvases;
int canvasSwitchCount; int canvasSwitchCount;
int drawCallsBatched;
Capabilities capabilities; Capabilities capabilities;
+78 -1
View File
@@ -564,11 +564,88 @@ bool Mesh::getDrawRange(int &start, int &count) const
return true; return true;
} }
void Mesh::draw(love::graphics::Graphics *gfx, const love::Matrix4 &m) void Mesh::draw(Graphics *gfx, const love::Matrix4 &m)
{ {
drawInstanced(gfx, m, 1); drawInstanced(gfx, m, 1);
} }
void Mesh::drawInstanced(Graphics *gfx, const Matrix4 &m, int instancecount)
{
if (vertexCount <= 0 || instancecount <= 0)
return;
if (instancecount > 1 && !gfx->getCapabilities().features[Graphics::FEATURE_INSTANCING])
throw love::Exception("Instancing is not supported on this system.");
gfx->flushStreamDraws();
if (Shader::isDefaultActive())
Shader::attachDefault(Shader::STANDARD_DEFAULT);
if (Shader::current && texture.get())
Shader::current->checkMainTexture(texture);
uint32 enabledattribs = 0;
uint32 instancedattribs = 0;
for (const auto &attrib : attachedAttributes)
{
if (!attrib.second.enabled)
continue;
love::graphics::Mesh *mesh = attrib.second.mesh;
int location = mesh->bindAttributeToShaderInput(attrib.second.index, attrib.first);
if (location >= 0)
{
uint32 bit = 1u << (uint32) location;
enabledattribs |= bit;
if (attrib.second.step == STEP_PER_INSTANCE)
instancedattribs |= bit;
}
}
// Not supported on all platforms or GL versions, I believe.
if (!(enabledattribs & ATTRIBFLAG_POS))
throw love::Exception("Mesh must have an enabled VertexPosition attribute to be drawn.");
bool useindexbuffer = useIndexBuffer && ibo != nullptr && elementCount > 0;
int start = 0;
int count = 0;
if (useindexbuffer)
{
// Make sure the index buffer isn't mapped (sends data to GPU if needed.)
ibo->unmap();
start = std::min(std::max(0, rangeStart), (int) elementCount - 1);
count = (int) elementCount;
if (rangeCount > 0)
count = std::min(count, rangeCount);
count = std::min(count, (int) elementCount - start);
}
else
{
start = std::min(std::max(0, rangeStart), (int) vertexCount - 1);
count = (int) vertexCount;
if (rangeCount > 0)
count = std::min(count, rangeCount);
count = std::min(count, (int) vertexCount - start);
}
Graphics::TempTransform transform(gfx, m);
if (count > 0)
drawInternal(start, count, instancecount, useindexbuffer, enabledattribs, instancedattribs);
}
size_t Mesh::getAttribFormatSize(const AttribFormat &format) size_t Mesh::getAttribFormatSize(const AttribFormat &format)
{ {
switch (format.type) switch (format.type)
+4 -2
View File
@@ -195,11 +195,11 @@ public:
virtual int bindAttributeToShaderInput(int attributeindex, const std::string &inputname) = 0; virtual int bindAttributeToShaderInput(int attributeindex, const std::string &inputname) = 0;
virtual void drawInstanced(Graphics *gfx, const Matrix4 &m, int instancecount) = 0;
// Implements Drawable. // Implements Drawable.
void draw(Graphics *gfx, const Matrix4 &m) override; void draw(Graphics *gfx, const Matrix4 &m) override;
void drawInstanced(Graphics *gfx, const Matrix4 &m, int instancecount);
static bool getConstant(const char *in, DrawMode &out); static bool getConstant(const char *in, DrawMode &out);
static bool getConstant(DrawMode in, const char *&out); static bool getConstant(DrawMode in, const char *&out);
@@ -223,6 +223,8 @@ protected:
void calculateAttributeSizes(); void calculateAttributeSizes();
size_t getAttributeOffset(size_t attribindex) const; size_t getAttributeOffset(size_t attribindex) const;
virtual void drawInternal(int start, int count, int instancecount, bool useindexbuffer, uint32 attribflags, uint32 instancedattribflags) const = 0;
static size_t getAttribFormatSize(const AttribFormat &format); static size_t getAttribFormatSize(const AttribFormat &format);
static std::vector<AttribFormat> getDefaultVertexFormat(); static std::vector<AttribFormat> getDefaultVertexFormat();
+10 -3
View File
@@ -1048,15 +1048,21 @@ void ParticleSystem::update(float dt)
prevPosition = position; prevPosition = position;
} }
bool ParticleSystem::prepareDraw(Graphics *gfx) void ParticleSystem::draw(Graphics *gfx, const Matrix4 &m)
{ {
uint32 pCount = getCount(); uint32 pCount = getCount();
if (pCount == 0 || texture.get() == nullptr || pMem == nullptr || buffer == nullptr) if (pCount == 0 || texture.get() == nullptr || pMem == nullptr || buffer == nullptr)
return false; return;
gfx->flushStreamDraws(); gfx->flushStreamDraws();
if (Shader::isDefaultActive())
Shader::attachDefault(Shader::STANDARD_DEFAULT);
if (Shader::current && texture.get())
Shader::current->checkMainTexture(texture);
const Vector2 *positions = texture->getQuad()->getVertexPositions(); const Vector2 *positions = texture->getQuad()->getVertexPositions();
const Vector2 *texcoords = texture->getQuad()->getVertexTexCoords(); const Vector2 *texcoords = texture->getQuad()->getVertexTexCoords();
@@ -1098,7 +1104,8 @@ bool ParticleSystem::prepareDraw(Graphics *gfx)
buffer->unmap(); buffer->unmap();
return true; Graphics::TempTransform transform(gfx, m);
drawInternal();
} }
bool ParticleSystem::getConstant(const char *in, AreaSpreadDistribution &out) bool ParticleSystem::getConstant(const char *in, AreaSpreadDistribution &out)
+5 -2
View File
@@ -25,8 +25,8 @@
#include "common/int.h" #include "common/int.h"
#include "common/math.h" #include "common/math.h"
#include "common/Vector.h" #include "common/Vector.h"
#include "common/Color.h"
#include "Drawable.h" #include "Drawable.h"
#include "Color.h"
#include "Quad.h" #include "Quad.h"
#include "Texture.h" #include "Texture.h"
#include "Buffer.h" #include "Buffer.h"
@@ -569,6 +569,9 @@ public:
**/ **/
void update(float dt); void update(float dt);
// Implements Drawable.
void draw(Graphics *gfx, const Matrix4 &m) override;
static bool getConstant(const char *in, AreaSpreadDistribution &out); static bool getConstant(const char *in, AreaSpreadDistribution &out);
static bool getConstant(AreaSpreadDistribution in, const char *&out); static bool getConstant(AreaSpreadDistribution in, const char *&out);
@@ -612,7 +615,7 @@ protected:
int quadIndex; int quadIndex;
}; };
bool prepareDraw(Graphics *gfx); virtual void drawInternal() const = 0;
// Pointer to the beginning of the allocated memory. // Pointer to the beginning of the allocated memory.
Particle *pMem; Particle *pMem;
+8 -8
View File
@@ -33,7 +33,7 @@ namespace love
namespace graphics namespace graphics
{ {
void Polyline::render(const float *coords, size_t count, size_t size_hint, float halfwidth, float pixel_size, bool draw_overdraw) void Polyline::render(const Vector2 *coords, size_t count, size_t size_hint, float halfwidth, float pixel_size, bool draw_overdraw)
{ {
static std::vector<Vector2> anchors; static std::vector<Vector2> anchors;
anchors.clear(); anchors.clear();
@@ -48,26 +48,26 @@ void Polyline::render(const float *coords, size_t count, size_t size_hint, float
halfwidth -= pixel_size * 0.3f; halfwidth -= pixel_size * 0.3f;
// compute sleeve // compute sleeve
bool is_looping = (coords[0] == coords[count - 2]) && (coords[1] == coords[count - 1]); bool is_looping = (coords[0] == coords[count - 1]);
Vector2 s; Vector2 s;
if (!is_looping) // virtual starting point at second point mirrored on first point if (!is_looping) // virtual starting point at second point mirrored on first point
s = Vector2(coords[2] - coords[0], coords[3] - coords[1]); s = coords[1] - coords[0];
else // virtual starting point at last vertex else // virtual starting point at last vertex
s = Vector2(coords[0] - coords[count - 4], coords[1] - coords[count - 3]); s = coords[0] - coords[count - 2];
float len_s = s.getLength(); float len_s = s.getLength();
Vector2 ns = s.getNormal(halfwidth / len_s); Vector2 ns = s.getNormal(halfwidth / len_s);
Vector2 q, r(coords[0], coords[1]); Vector2 q, r(coords[0]);
for (size_t i = 0; i + 3 < count; i += 2) for (size_t i = 0; i + 1 < count; i++)
{ {
q = r; q = r;
r = Vector2(coords[i + 2], coords[i + 3]); r = coords[i + 1];
renderEdge(anchors, normals, s, len_s, ns, q, r, halfwidth); renderEdge(anchors, normals, s, len_s, ns, q, r, halfwidth);
} }
q = r; q = r;
r = is_looping ? Vector2(coords[2], coords[3]) : r + s; r = is_looping ? coords[1] : r + s;
renderEdge(anchors, normals, s, len_s, ns, q, r, halfwidth); renderEdge(anchors, normals, s, len_s, ns, q, r, halfwidth);
vertex_count = normals.size(); vertex_count = normals.size();
+8 -8
View File
@@ -57,13 +57,13 @@ public:
/** /**
* @param vertices Vertices defining the core line segments * @param vertices Vertices defining the core line segments
* @param count Number of coordinates (= size of the array vertices) * @param count Number of vertices
* @param size_hint Expected number of vertices of the rendering sleeve around the core line. * @param size_hint Expected number of vertices of the rendering sleeve around the core line.
* @param halfwidth linewidth / 2. * @param halfwidth linewidth / 2.
* @param pixel_size Dimension of one pixel on the screen in world coordinates. * @param pixel_size Dimension of one pixel on the screen in world coordinates.
* @param draw_overdraw Fake antialias the line. * @param draw_overdraw Fake antialias the line.
*/ */
void render(const float *vertices, size_t count, size_t size_hint, float halfwidth, float pixel_size, bool draw_overdraw); void render(const Vector2 *vertices, size_t count, size_t size_hint, float halfwidth, float pixel_size, bool draw_overdraw);
/** Draws the line on the screen /** Draws the line on the screen
*/ */
@@ -112,9 +112,9 @@ public:
: Polyline(vertex::TriangleIndexMode::QUADS) : Polyline(vertex::TriangleIndexMode::QUADS)
{} {}
void render(const float *vertices, size_t count, float halfwidth, float pixel_size, bool draw_overdraw) void render(const Vector2 *vertices, size_t count, float halfwidth, float pixel_size, bool draw_overdraw)
{ {
Polyline::render(vertices, count, 2 * count - 4, halfwidth, pixel_size, draw_overdraw); Polyline::render(vertices, count, 4 * count - 4, halfwidth, pixel_size, draw_overdraw);
// discard the first and last two vertices. (these are redundant) // discard the first and last two vertices. (these are redundant)
for (size_t i = 0; i < vertex_count - 4; ++i) for (size_t i = 0; i < vertex_count - 4; ++i)
@@ -149,9 +149,9 @@ class MiterJoinPolyline : public Polyline
{ {
public: public:
void render(const float *vertices, size_t count, float halfwidth, float pixel_size, bool draw_overdraw) void render(const Vector2 *vertices, size_t count, float halfwidth, float pixel_size, bool draw_overdraw)
{ {
Polyline::render(vertices, count, count, halfwidth, pixel_size, draw_overdraw); Polyline::render(vertices, count, 2 * count, halfwidth, pixel_size, draw_overdraw);
} }
protected: protected:
@@ -171,9 +171,9 @@ class BevelJoinPolyline : public Polyline
{ {
public: public:
void render(const float *vertices, size_t count, float halfwidth, float pixel_size, bool draw_overdraw) void render(const Vector2 *vertices, size_t count, float halfwidth, float pixel_size, bool draw_overdraw)
{ {
Polyline::render(vertices, count, 2 * count - 4, halfwidth, pixel_size, draw_overdraw); Polyline::render(vertices, count, 4 * count - 4, halfwidth, pixel_size, draw_overdraw);
} }
protected: protected:
+10 -10
View File
@@ -351,16 +351,16 @@ StringMap<Shader::ShaderStage, Shader::STAGE_MAX_ENUM> Shader::stageNames(Shader
StringMap<Shader::BuiltinUniform, Shader::BUILTIN_MAX_ENUM>::Entry Shader::builtinNameEntries[] = StringMap<Shader::BuiltinUniform, Shader::BUILTIN_MAX_ENUM>::Entry Shader::builtinNameEntries[] =
{ {
{ "MainTex", BUILTIN_TEXTURE_MAIN }, { "MainTex", BUILTIN_TEXTURE_MAIN },
{ "love_VideoYChannel", BUILTIN_TEXTURE_VIDEO_Y }, { "love_VideoYChannel", BUILTIN_TEXTURE_VIDEO_Y },
{ "love_VideoCbChannel", BUILTIN_TEXTURE_VIDEO_CB }, { "love_VideoCbChannel", BUILTIN_TEXTURE_VIDEO_CB },
{ "love_VideoCrChannel", BUILTIN_TEXTURE_VIDEO_CR }, { "love_VideoCrChannel", BUILTIN_TEXTURE_VIDEO_CR },
{ "TransformMatrix", BUILTIN_MATRIX_TRANSFORM }, { "ViewSpaceFromLocal", BUILTIN_MATRIX_VIEW_FROM_LOCAL },
{ "ProjectionMatrix", BUILTIN_MATRIX_PROJECTION }, { "ClipSpaceFromView", BUILTIN_MATRIX_CLIP_FROM_VIEW },
{ "TransformProjectionMatrix", BUILTIN_MATRIX_TRANSFORM_PROJECTION }, { "ClipSpaceFromLocal", BUILTIN_MATRIX_CLIP_FROM_LOCAL },
{ "NormalMatrix", BUILTIN_MATRIX_NORMAL }, { "ViewNormalFromLocal", BUILTIN_MATRIX_VIEW_NORMAL_FROM_LOCAL },
{ "love_PointSize", BUILTIN_POINT_SIZE }, { "love_PointSize", BUILTIN_POINT_SIZE },
{ "love_ScreenSize", BUILTIN_SCREEN_SIZE }, { "love_ScreenSize", BUILTIN_SCREEN_SIZE },
}; };
StringMap<Shader::BuiltinUniform, Shader::BUILTIN_MAX_ENUM> Shader::builtinNames(Shader::builtinNameEntries, sizeof(Shader::builtinNameEntries)); StringMap<Shader::BuiltinUniform, Shader::BUILTIN_MAX_ENUM> Shader::builtinNames(Shader::builtinNameEntries, sizeof(Shader::builtinNameEntries));
+4 -4
View File
@@ -73,10 +73,10 @@ public:
BUILTIN_TEXTURE_VIDEO_Y, BUILTIN_TEXTURE_VIDEO_Y,
BUILTIN_TEXTURE_VIDEO_CB, BUILTIN_TEXTURE_VIDEO_CB,
BUILTIN_TEXTURE_VIDEO_CR, BUILTIN_TEXTURE_VIDEO_CR,
BUILTIN_MATRIX_TRANSFORM, BUILTIN_MATRIX_VIEW_FROM_LOCAL,
BUILTIN_MATRIX_PROJECTION, BUILTIN_MATRIX_CLIP_FROM_VIEW,
BUILTIN_MATRIX_TRANSFORM_PROJECTION, BUILTIN_MATRIX_CLIP_FROM_LOCAL,
BUILTIN_MATRIX_NORMAL, BUILTIN_MATRIX_VIEW_NORMAL_FROM_LOCAL,
BUILTIN_POINT_SIZE, BUILTIN_POINT_SIZE,
BUILTIN_SCREEN_SIZE, BUILTIN_SCREEN_SIZE,
BUILTIN_MAX_ENUM BUILTIN_MAX_ENUM
+62 -8
View File
@@ -62,9 +62,9 @@ SpriteBatch::SpriteBatch(Graphics *gfx, Texture *texture, int size, vertex::Usag
else else
vertex_format = vertex::CommonFormat::XYf_STf_RGBAub; vertex_format = vertex::CommonFormat::XYf_STf_RGBAub;
format_stride = vertex::getFormatStride(vertex_format); vertex_stride = vertex::getFormatStride(vertex_format);
size_t vertex_size = format_stride * 4 * size; size_t vertex_size = vertex_stride * 4 * size;
array_buf = gfx->newBuffer(vertex_size, nullptr, BUFFER_VERTEX, usage, Buffer::MAP_EXPLICIT_RANGE_MODIFY); array_buf = gfx->newBuffer(vertex_size, nullptr, BUFFER_VERTEX, usage, Buffer::MAP_EXPLICIT_RANGE_MODIFY);
} }
@@ -95,7 +95,7 @@ int SpriteBatch::add(Quad *quad, const Matrix4 &m, int index /*= -1*/)
const Vector2 *quadtexcoords = quad->getVertexTexCoords(); const Vector2 *quadtexcoords = quad->getVertexTexCoords();
// Always keep the VBO mapped when adding data (it'll be unmapped on draw.) // Always keep the VBO mapped when adding data (it'll be unmapped on draw.)
size_t offset = (index == -1 ? next : index) * format_stride * 4; size_t offset = (index == -1 ? next : index) * vertex_stride * 4;
auto verts = (XYf_STf_RGBAub *) ((uint8 *) array_buf->map() + offset); auto verts = (XYf_STf_RGBAub *) ((uint8 *) array_buf->map() + offset);
m.transformXY(verts, quadpositions, 4); m.transformXY(verts, quadpositions, 4);
@@ -107,7 +107,7 @@ int SpriteBatch::add(Quad *quad, const Matrix4 &m, int index /*= -1*/)
verts[i].color = color; verts[i].color = color;
} }
array_buf->setMappedRangeModified(offset, format_stride * 4); array_buf->setMappedRangeModified(offset, vertex_stride * 4);
// Increment counter. // Increment counter.
if (index == -1) if (index == -1)
@@ -141,7 +141,7 @@ int SpriteBatch::addLayer(int layer, Quad *quad, const Matrix4 &m, int index)
const Vector2 *quadtexcoords = quad->getVertexTexCoords(); const Vector2 *quadtexcoords = quad->getVertexTexCoords();
// Always keep the VBO mapped when adding data (it'll be unmapped on draw.) // Always keep the VBO mapped when adding data (it'll be unmapped on draw.)
size_t offset = (index == -1 ? next : index) * format_stride * 4; size_t offset = (index == -1 ? next : index) * vertex_stride * 4;
auto verts = (XYf_STPf_RGBAub *) ((uint8 *) array_buf->map() + offset); auto verts = (XYf_STPf_RGBAub *) ((uint8 *) array_buf->map() + offset);
m.transformXY(verts, quadpositions, 4); m.transformXY(verts, quadpositions, 4);
@@ -154,7 +154,7 @@ int SpriteBatch::addLayer(int layer, Quad *quad, const Matrix4 &m, int index)
verts[i].color = color; verts[i].color = color;
} }
array_buf->setMappedRangeModified(offset, format_stride * 4); array_buf->setMappedRangeModified(offset, vertex_stride * 4);
// Increment counter. // Increment counter.
if (index == -1) if (index == -1)
@@ -225,7 +225,7 @@ void SpriteBatch::setBufferSize(int newsize)
if (newsize == size) if (newsize == size)
return; return;
size_t vertex_size = format_stride * 4 * newsize; size_t vertex_size = vertex_stride * 4 * newsize;
love::graphics::Buffer *new_array_buf = nullptr; love::graphics::Buffer *new_array_buf = nullptr;
int new_next = std::min(next, newsize); int new_next = std::min(next, newsize);
@@ -236,7 +236,7 @@ void SpriteBatch::setBufferSize(int newsize)
new_array_buf = gfx->newBuffer(vertex_size, nullptr, array_buf->getType(), array_buf->getUsage(), array_buf->getMapFlags()); new_array_buf = gfx->newBuffer(vertex_size, nullptr, array_buf->getType(), array_buf->getUsage(), array_buf->getMapFlags());
// Copy as much of the old data into the new GLBuffer as can fit. // Copy as much of the old data into the new GLBuffer as can fit.
size_t copy_size = format_stride * 4 * new_next; size_t copy_size = vertex_stride * 4 * new_next;
array_buf->copyTo(0, copy_size, new_array_buf, 0); array_buf->copyTo(0, copy_size, new_array_buf, 0);
quad_indices = QuadIndices(gfx, newsize); quad_indices = QuadIndices(gfx, newsize);
@@ -307,5 +307,59 @@ bool SpriteBatch::getDrawRange(int &start, int &count) const
return true; return true;
} }
void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m)
{
using namespace vertex;
if (next == 0)
return;
gfx->flushStreamDraws();
if (texture.get())
{
if (Shader::isDefaultActive())
{
Shader::StandardShader defaultshader = Shader::STANDARD_DEFAULT;
if (texture->getTextureType() == TEXTURE_2D_ARRAY)
defaultshader = Shader::STANDARD_ARRAY;
Shader::attachDefault(defaultshader);
}
if (Shader::current)
Shader::current->checkMainTexture(texture);
}
// Make sure the VBO isn't mapped when we draw (sends data to GPU if needed.)
array_buf->unmap();
CommonFormat format = vertex_format;
if (!color_active)
{
if (format == CommonFormat::XYf_STPf_RGBAub)
format = CommonFormat::XYf_STPf;
else
format = CommonFormat::XYf_STf;
}
int start = std::min(std::max(0, range_start), next - 1);
int count = next;
if (range_count > 0)
count = std::min(count, range_count);
count = std::min(count, next - start);
size_t indexbytestart = quad_indices.getIndexCount(start) * quad_indices.getElementSize();
size_t indexcount = quad_indices.getIndexCount(count);
Graphics::TempTransform transform(gfx, m);
if (count > 0)
drawInternal(format, indexbytestart, indexcount);
}
} // graphics } // graphics
} // love } // love
+8 -2
View File
@@ -29,9 +29,10 @@
// LOVE // LOVE
#include "common/math.h" #include "common/math.h"
#include "common/Matrix.h" #include "common/Matrix.h"
#include "common/Color.h"
#include "Drawable.h" #include "Drawable.h"
#include "Color.h"
#include "Mesh.h" #include "Mesh.h"
#include "vertex.h"
namespace love namespace love
{ {
@@ -105,6 +106,9 @@ public:
void setDrawRange(); void setDrawRange();
bool getDrawRange(int &start, int &count) const; bool getDrawRange(int &start, int &count) const;
// Implements Drawable.
void draw(Graphics *gfx, const Matrix4 &m) override;
protected: protected:
struct AttachedAttribute struct AttachedAttribute
@@ -119,6 +123,8 @@ protected:
**/ **/
void setBufferSize(int newsize); void setBufferSize(int newsize);
virtual void drawInternal(vertex::CommonFormat format, size_t indexbytestart, size_t indexcount) = 0;
StrongRef<Texture> texture; StrongRef<Texture> texture;
// Max number of sprites in the batch. // Max number of sprites in the batch.
@@ -133,7 +139,7 @@ protected:
bool color_active; bool color_active;
vertex::CommonFormat vertex_format; vertex::CommonFormat vertex_format;
size_t format_stride; size_t vertex_stride;
love::graphics::Buffer *array_buf; love::graphics::Buffer *array_buf;
QuadIndices quad_indices; QuadIndices quad_indices;
+31
View File
@@ -235,5 +235,36 @@ int Text::getHeight(int index) const
return text_data[index].text_info.height; return text_data[index].text_info.height;
} }
void Text::draw(Graphics *gfx, const Matrix4 &m)
{
if (vbo == nullptr || draw_commands.empty())
return;
gfx->flushStreamDraws();
if (Shader::isDefaultActive())
Shader::attachDefault(Shader::STANDARD_DEFAULT);
if (Shader::current)
Shader::current->checkMainTextureType(TEXTURE_2D, false);
// Re-generate the text if the Font's texture cache was invalidated.
if (font->getTextureCacheID() != texture_cache_id)
regenerateVertices();
int totalverts = 0;
for (const Font::DrawCommand &cmd : draw_commands)
totalverts = std::max(cmd.startvertex + cmd.vertexcount, totalverts);
if ((size_t) totalverts / 4 > quadIndices.getSize())
quadIndices = QuadIndices(gfx, (size_t) totalverts / 4);
vbo->unmap(); // Make sure all pending data is flushed to the GPU.
Graphics::TempTransform transform(gfx, m);
drawInternal(draw_commands);
}
} // graphics } // graphics
} // love } // love
+5
View File
@@ -63,6 +63,9 @@ public:
**/ **/
int getHeight(int index = 0) const; int getHeight(int index = 0) const;
// Implements Drawable.
void draw(love::graphics::Graphics *gfx, const Matrix4 &m) override;
protected: protected:
struct TextData struct TextData
@@ -80,6 +83,8 @@ protected:
void regenerateVertices(); void regenerateVertices();
void addTextData(const TextData &s); void addTextData(const TextData &s);
virtual void drawInternal(const std::vector<Font::DrawCommand> &commands) const = 0;
StrongRef<Font> font; StrongRef<Font> font;
Buffer *vbo; Buffer *vbo;
QuadIndices quadIndices; QuadIndices quadIndices;
+57
View File
@@ -317,6 +317,63 @@ int Texture::getMipmapCount(int w, int h, int d)
return (int) log2(std::max(std::max(w, h), d)) + 1; return (int) log2(std::max(std::max(w, h), d)) + 1;
} }
bool Texture::validateDimensions(bool throwException) const
{
bool success = true;
auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS);
if (gfx == nullptr)
return false;
const Graphics::Capabilities &caps = gfx->getCapabilities();
int max2Dsize = (int) caps.limits[Graphics::LIMIT_TEXTURE_SIZE];
int max3Dsize = (int) caps.limits[Graphics::LIMIT_VOLUME_TEXTURE_SIZE];
int maxcubesize = (int) caps.limits[Graphics::LIMIT_CUBE_TEXTURE_SIZE];
int maxlayers = (int) caps.limits[Graphics::LIMIT_TEXTURE_LAYERS];
int largestdim = 0;
const char *largestname = nullptr;
if ((texType == TEXTURE_2D || texType == TEXTURE_2D_ARRAY) && (pixelWidth > max2Dsize || pixelHeight > max2Dsize))
{
success = false;
largestdim = std::max(pixelWidth, pixelHeight);
largestname = pixelWidth > pixelHeight ? "pixel width" : "pixel height";
}
else if (texType == TEXTURE_2D_ARRAY && layers > maxlayers)
{
success = false;
largestdim = layers;
largestname = "array layer count";
}
else if (texType == TEXTURE_CUBE && (pixelWidth > maxcubesize || pixelWidth != pixelHeight))
{
success = false;
largestdim = std::max(pixelWidth, pixelHeight);
largestname = pixelWidth > pixelHeight ? "pixel width" : "pixel height";
if (throwException && pixelWidth != pixelHeight)
throw love::Exception("Cubemap textures must have equal width and height.");
}
else if (texType == TEXTURE_VOLUME && (pixelWidth > max3Dsize || pixelHeight > max3Dsize || depth > max3Dsize))
{
success = false;
largestdim = std::max(std::max(pixelWidth, pixelHeight), depth);
if (largestdim == pixelWidth)
largestname = "pixel width";
else if (largestdim == pixelHeight)
largestname = "pixel height";
else
largestname = "pixel depth";
}
if (throwException && largestname != nullptr)
throw love::Exception("Cannot create texture: %s of %d is too large for this system.", largestname, largestdim);
return success;
}
bool Texture::getConstant(const char *in, TextureType &out) bool Texture::getConstant(const char *in, TextureType &out)
{ {
return texTypes.find(in, out); return texTypes.find(in, out);
+2
View File
@@ -174,6 +174,8 @@ protected:
void initQuad(); void initQuad();
void setGraphicsMemorySize(int64 size); void setGraphicsMemorySize(int64 size);
bool validateDimensions(bool throwException) const;
TextureType texType; TextureType texType;
PixelFormat format; PixelFormat format;
+1 -1
View File
@@ -22,7 +22,7 @@
#define LOVE_GRAPHICS_OPENGL_CANVAS_H #define LOVE_GRAPHICS_OPENGL_CANVAS_H
#include "common/config.h" #include "common/config.h"
#include "graphics/Color.h" #include "common/Color.h"
#include "common/int.h" #include "common/int.h"
#include "graphics/Canvas.h" #include "graphics/Canvas.h"
#include "graphics/Volatile.h" #include "graphics/Volatile.h"
+6 -118
View File
@@ -492,107 +492,9 @@ void Graphics::setDebug(bool enable)
::printf("OpenGL debug output enabled (LOVE_GRAPHICS_DEBUG=1)\n"); ::printf("OpenGL debug output enabled (LOVE_GRAPHICS_DEBUG=1)\n");
} }
void Graphics::setCanvas(const RenderTargets &rts) void Graphics::setCanvasInternal(const RenderTargets &rts, int w, int h, int pixelw, int pixelh, bool hasSRGBcanvas)
{ {
DisplayState &state = states.back(); const DisplayState &state = states.back();
int ncanvases = (int) rts.colors.size();
if (ncanvases == 0 && rts.depthStencil.canvas == nullptr)
return setCanvas();
else if (ncanvases == 0)
throw love::Exception("At least one color render target is required when using a custom depth/stencil buffer.");
const auto &prevRTs = state.renderTargets;
if (ncanvases == (int) prevRTs.colors.size())
{
bool modified = false;
for (int i = 0; i < ncanvases; i++)
{
if (rts.colors[i].canvas != prevRTs.colors[i].canvas.get()
|| rts.colors[i].slice != prevRTs.colors[i].slice
|| rts.colors[i].mipmap != prevRTs.colors[i].mipmap)
{
modified = true;
break;
}
}
if (!modified && (rts.depthStencil.canvas != prevRTs.depthStencil.canvas
|| rts.depthStencil.slice != prevRTs.depthStencil.slice
|| rts.depthStencil.mipmap != prevRTs.depthStencil.mipmap))
{
modified = true;
}
if (rts.temporaryRTFlags != prevRTs.temporaryRTFlags)
modified = true;
if (!modified)
return;
}
if (ncanvases > gl.getMaxRenderTargets())
throw love::Exception("This system can't simultaneously render to %d canvases.", ncanvases);
love::graphics::Canvas *firstcanvas = rts.colors[0].canvas;
bool multiformatsupported = Canvas::isMultiFormatMultiCanvasSupported();
PixelFormat firstformat = firstcanvas->getPixelFormat();
if (isPixelFormatDepthStencil(firstformat))
throw love::Exception("Depth/stencil format Canvases must be used with the 'depthstencil' field of the table passed into setCanvas.");
if (rts.colors[0].mipmap < 0 || rts.colors[0].mipmap >= firstcanvas->getMipmapCount())
throw love::Exception("Invalid mipmap level %d.", rts.colors[0].mipmap + 1);
bool hasSRGBcanvas = firstformat == PIXELFORMAT_sRGBA8;
int pixelwidth = firstcanvas->getPixelWidth(rts.colors[0].mipmap);
int pixelheight = firstcanvas->getPixelHeight(rts.colors[0].mipmap);
for (int i = 1; i < ncanvases; i++)
{
love::graphics::Canvas *c = rts.colors[i].canvas;
PixelFormat format = c->getPixelFormat();
int mip = rts.colors[i].mipmap;
if (mip < 0 || mip >= c->getMipmapCount())
throw love::Exception("Invalid mipmap level %d.", mip + 1);
if (c->getPixelWidth(mip) != pixelwidth || c->getPixelHeight(mip) != pixelheight)
throw love::Exception("All canvases must have the same pixel dimensions.");
if (!multiformatsupported && format != firstformat)
throw love::Exception("This system doesn't support multi-canvas rendering with different canvas formats.");
if (c->getRequestedMSAA() != firstcanvas->getRequestedMSAA())
throw love::Exception("All Canvases must have the same MSAA value.");
if (isPixelFormatDepthStencil(format))
throw love::Exception("Depth/stencil format Canvases must be used with the 'depthstencil' field of the table passed into setCanvas.");
if (format == PIXELFORMAT_sRGBA8)
hasSRGBcanvas = true;
}
if (rts.depthStencil.canvas != nullptr)
{
love::graphics::Canvas *c = rts.depthStencil.canvas;
int mip = rts.depthStencil.mipmap;
if (!isPixelFormatDepthStencil(c->getPixelFormat()))
throw love::Exception("Only depth/stencil format Canvases can be used with the 'depthstencil' field of the table passed into setCanvas.");
if (c->getPixelWidth(mip) != pixelwidth || c->getPixelHeight(mip) != pixelheight)
throw love::Exception("All canvases must have the same pixel dimensions.");
if (c->getRequestedMSAA() != firstcanvas->getRequestedMSAA())
throw love::Exception("All Canvases must have the same MSAA value.");
if (mip < 0 || mip >= c->getMipmapCount())
throw love::Exception("Invalid mipmap level %d.", mip + 1);
}
OpenGL::TempDebugGroup debuggroup("setCanvas(...)"); OpenGL::TempDebugGroup debuggroup("setCanvas(...)");
@@ -600,15 +502,13 @@ void Graphics::setCanvas(const RenderTargets &rts)
bindCachedFBO(rts); bindCachedFBO(rts);
gl.setViewport({0, 0, pixelwidth, pixelheight}); gl.setViewport({0, 0, pixelw, pixelh});
// Re-apply the scissor if it was active, since the rectangle passed to // Re-apply the scissor if it was active, since the rectangle passed to
// glScissor is affected by the viewport dimensions. // glScissor is affected by the viewport dimensions.
if (state.scissor) if (state.scissor)
setScissor(state.scissorRect); setScissor(state.scissorRect);
int w = firstcanvas->getWidth(rts.colors[0].mipmap);
int h = firstcanvas->getHeight(rts.colors[0].mipmap);
projectionMatrix = Matrix4::ortho(0.0, (float) w, 0.0, (float) h); projectionMatrix = Matrix4::ortho(0.0, (float) w, 0.0, (float) h);
// Make sure the correct sRGB setting is used when drawing to the canvases. // Make sure the correct sRGB setting is used when drawing to the canvases.
@@ -619,19 +519,6 @@ void Graphics::setCanvas(const RenderTargets &rts)
else if (!hasSRGBcanvas && gl.hasFramebufferSRGB()) else if (!hasSRGBcanvas && gl.hasFramebufferSRGB())
gl.setFramebufferSRGB(false); gl.setFramebufferSRGB(false);
} }
RenderTargetsStrongRef refs;
refs.colors.reserve(rts.colors.size());
for (auto c : rts.colors)
refs.colors.emplace_back(c.canvas, c.slice);
refs.depthStencil = RenderTargetStrongRef(rts.depthStencil.canvas, rts.depthStencil.slice);
refs.temporaryRTFlags = rts.temporaryRTFlags;
std::swap(state.renderTargets, refs);
canvasSwitchCount++;
} }
void Graphics::setCanvas() void Graphics::setCanvas()
@@ -643,6 +530,7 @@ void Graphics::setCanvas()
OpenGL::TempDebugGroup debuggroup("setCanvas()"); OpenGL::TempDebugGroup debuggroup("setCanvas()");
flushStreamDraws();
endPass(); endPass();
state.renderTargets = RenderTargetsStrongRef(); state.renderTargets = RenderTargetsStrongRef();
@@ -673,8 +561,6 @@ void Graphics::setCanvas()
void Graphics::endPass() void Graphics::endPass()
{ {
flushStreamDraws();
auto &rts = states.back().renderTargets; auto &rts = states.back().renderTargets;
love::graphics::Canvas *depthstencil = rts.depthStencil.canvas.get(); love::graphics::Canvas *depthstencil = rts.depthStencil.canvas.get();
@@ -1013,6 +899,7 @@ void Graphics::present(void *screenshotCallbackData)
if (isCanvasActive()) if (isCanvasActive())
throw love::Exception("present cannot be called while a Canvas is active."); throw love::Exception("present cannot be called while a Canvas is active.");
flushStreamDraws();
endPass(); endPass();
gl.bindFramebuffer(OpenGL::FRAMEBUFFER_ALL, gl.getDefaultFBO()); gl.bindFramebuffer(OpenGL::FRAMEBUFFER_ALL, gl.getDefaultFBO());
@@ -1123,6 +1010,7 @@ void Graphics::present(void *screenshotCallbackData)
gl.stats.drawCalls = 0; gl.stats.drawCalls = 0;
gl.stats.shaderSwitches = 0; gl.stats.shaderSwitches = 0;
canvasSwitchCount = 0; canvasSwitchCount = 0;
drawCallsBatched = 0;
} }
void Graphics::setScissor(const Rect &rect) void Graphics::setScissor(const Rect &rect)
+2 -2
View File
@@ -31,7 +31,7 @@
// LOVE // LOVE
#include "graphics/Graphics.h" #include "graphics/Graphics.h"
#include "graphics/Color.h" #include "common/Color.h"
#include "image/Image.h" #include "image/Image.h"
#include "image/ImageData.h" #include "image/ImageData.h"
@@ -97,7 +97,6 @@ public:
void setColor(Colorf c) override; void setColor(Colorf c) override;
void setCanvas(const RenderTargets &rts) override;
void setCanvas() override; void setCanvas() override;
void setScissor(const Rect &rect) override; void setScissor(const Rect &rect) override;
@@ -128,6 +127,7 @@ public:
private: private:
love::graphics::StreamBuffer *newStreamBuffer(BufferType type, size_t size) override; love::graphics::StreamBuffer *newStreamBuffer(BufferType type, size_t size) override;
void setCanvasInternal(const RenderTargets &rts, int w, int h, int pixelw, int pixelh, bool hasSRGBcanvas) override;
void initCapabilities() override; void initCapabilities() override;
void getAPIStats(int &drawcalls, int &shaderswitches) const override; void getAPIStats(int &drawcalls, int &shaderswitches) const override;
+1 -15
View File
@@ -221,22 +221,8 @@ bool Image::loadVolatile()
glGenTextures(1, &texture); glGenTextures(1, &texture);
gl.bindTextureToUnit(this, 0, false); gl.bindTextureToUnit(this, 0, false);
bool loaddefault = false;
int max2Dsize = gl.getMax2DTextureSize();
int max3Dsize = gl.getMax3DTextureSize();
if ((texType == TEXTURE_2D || texType == TEXTURE_2D_ARRAY) && (pixelWidth > max2Dsize || pixelHeight > max2Dsize))
loaddefault = true;
else if (texType == TEXTURE_2D_ARRAY && layers > gl.getMaxTextureLayers())
loaddefault = true;
else if (texType == TEXTURE_CUBE && (pixelWidth > gl.getMaxCubeTextureSize() || pixelWidth != pixelHeight))
loaddefault = true;
else if (texType == TEXTURE_VOLUME && (pixelWidth > max3Dsize || pixelHeight > max3Dsize || depth > max3Dsize))
loaddefault = true;
// Use a default texture if the size is too big for the system. // Use a default texture if the size is too big for the system.
if (loaddefault) if (!validateDimensions(false))
{ {
loadDefaultTexture(); loadDefaultTexture();
return true; return true;
+8 -74
View File
@@ -91,94 +91,28 @@ int Mesh::bindAttributeToShaderInput(int attributeindex, const std::string &inpu
return attriblocation; return attriblocation;
} }
void Mesh::drawInstanced(love::graphics::Graphics *gfx, const love::Matrix4 &m, int instancecount) void Mesh::drawInternal(int start, int count, int instancecount, bool useindexbuffer, uint32 attribflags, uint32 instancedattribflags) const
{ {
if (vertexCount <= 0 || instancecount <= 0)
return;
if (instancecount > 1 && !gl.isInstancingSupported())
throw love::Exception("Instancing is not supported on this system.");
gfx->flushStreamDraws();
if (Shader::isDefaultActive())
Shader::attachDefault(Shader::STANDARD_DEFAULT);
if (Shader::current && texture.get())
Shader::current->checkMainTexture(texture);
OpenGL::TempDebugGroup debuggroup("Mesh draw"); OpenGL::TempDebugGroup debuggroup("Mesh draw");
uint32 enabledattribs = 0; gl.useVertexAttribArrays(attribflags, instancedattribflags);
uint32 instancedattribs = 0;
for (const auto &attrib : attachedAttributes)
{
if (!attrib.second.enabled)
continue;
love::graphics::Mesh *mesh = attrib.second.mesh;
int location = mesh->bindAttributeToShaderInput(attrib.second.index, attrib.first);
if (location >= 0)
{
uint32 bit = 1u << (uint32) location;
enabledattribs |= bit;
if (attrib.second.step == STEP_PER_INSTANCE)
instancedattribs |= bit;
}
}
// Not supported on all platforms or GL versions, I believe.
if (!(enabledattribs & ATTRIBFLAG_POS))
throw love::Exception("Mesh must have an enabled VertexPosition attribute to be drawn.");
gl.useVertexAttribArrays(enabledattribs, instancedattribs);
gl.bindTextureToUnit(texture, 0, false); gl.bindTextureToUnit(texture, 0, false);
Graphics::TempTransform transform(gfx, m);
gl.prepareDraw(); gl.prepareDraw();
if (useIndexBuffer && ibo && elementCount > 0) GLenum gldrawmode = getGLDrawMode(drawMode);
if (useindexbuffer)
{ {
// Use the custom vertex map (index buffer) to draw the vertices.
gl.bindBuffer(BUFFER_INDEX, (GLuint) ibo->getHandle());
// Make sure the index buffer isn't mapped (sends data to GPU if needed.)
ibo->unmap();
int start = std::min(std::max(0, rangeStart), (int) elementCount - 1);
int count = (int) elementCount;
if (rangeCount > 0)
count = std::min(count, rangeCount);
count = std::min(count, (int) elementCount - start);
size_t elementsize = vertex::getIndexDataSize(elementDataType); size_t elementsize = vertex::getIndexDataSize(elementDataType);
const void *indices = BUFFER_OFFSET(start * elementsize); const void *indices = BUFFER_OFFSET(start * elementsize);
GLenum type = OpenGL::getGLIndexDataType(elementDataType); GLenum type = OpenGL::getGLIndexDataType(elementDataType);
if (count > 0) gl.bindBuffer(BUFFER_INDEX, (GLuint) ibo->getHandle());
gl.drawElements(getGLDrawMode(drawMode), count, type, indices, instancecount); gl.drawElements(gldrawmode, count, type, indices, instancecount);
} }
else else
{ {
int start = std::min(std::max(0, rangeStart), (int) vertexCount - 1); gl.drawArrays(gldrawmode, start, count, instancecount);
int count = (int) vertexCount;
if (rangeCount > 0)
count = std::min(count, rangeCount);
count = std::min(count, (int) vertexCount - start);
// Normal non-indexed drawing (no custom vertex map.)
if (count > 0)
gl.drawArrays(getGLDrawMode(drawMode), start, count, instancecount);
} }
} }
+4 -1
View File
@@ -44,7 +44,10 @@ public:
virtual ~Mesh(); virtual ~Mesh();
int bindAttributeToShaderInput(int attributeindex, const std::string &inputname) override; int bindAttributeToShaderInput(int attributeindex, const std::string &inputname) override;
void drawInstanced(Graphics *gfx, const Matrix4 &m, int instancecount) override;
protected:
void drawInternal(int start, int count, int instancecount, bool useindexbuffer, uint32 attribflags, uint32 instancedattribflags) const override;
private: private:
+2 -1
View File
@@ -261,7 +261,8 @@ void OpenGL::initVendor()
// http://feedback.wildfiregames.com/report/opengl/feature/GL_VENDOR // http://feedback.wildfiregames.com/report/opengl/feature/GL_VENDOR
// http://stackoverflow.com/questions/2093594/opengl-extensions-available-on-different-android-devices // http://stackoverflow.com/questions/2093594/opengl-extensions-available-on-different-android-devices
if (strstr(vstr, "ATI Technologies")) // http://opengl.gpuinfo.org/gl_stats_caps_single.php?listreportsbycap=GL_VENDOR
if (strstr(vstr, "ATI Technologies") || strstr(vstr, "AMD") || strstr(vstr, "Advanced Micro Devices"))
vendor = VENDOR_AMD; vendor = VENDOR_AMD;
else if (strstr(vstr, "NVIDIA")) else if (strstr(vstr, "NVIDIA"))
vendor = VENDOR_NVIDIA; vendor = VENDOR_NVIDIA;
+1 -1
View File
@@ -25,7 +25,7 @@
#include "common/config.h" #include "common/config.h"
#include "common/int.h" #include "common/int.h"
#include "common/math.h" #include "common/math.h"
#include "graphics/Color.h" #include "common/Color.h"
#include "graphics/Texture.h" #include "graphics/Texture.h"
#include "graphics/vertex.h" #include "graphics/vertex.h"
#include "graphics/depthstencil.h" #include "graphics/depthstencil.h"
+1 -12
View File
@@ -50,21 +50,10 @@ ParticleSystem *ParticleSystem::clone()
return new ParticleSystem(*this); return new ParticleSystem(*this);
} }
void ParticleSystem::draw(Graphics *gfx, const Matrix4 &m) void ParticleSystem::drawInternal() const
{ {
using namespace vertex; using namespace vertex;
if (!prepareDraw(gfx))
return;
Graphics::TempTransform transform(gfx, m);
if (Shader::isDefaultActive())
Shader::attachDefault(Shader::STANDARD_DEFAULT);
if (Shader::current && texture.get())
Shader::current->checkMainTexture(texture);
OpenGL::TempDebugGroup debuggroup("ParticleSystem draw"); OpenGL::TempDebugGroup debuggroup("ParticleSystem draw");
gl.bindTextureToUnit(texture, 0, false); gl.bindTextureToUnit(texture, 0, false);
+4 -1
View File
@@ -44,7 +44,10 @@ public:
virtual ~ParticleSystem(); virtual ~ParticleSystem();
ParticleSystem *clone() override; ParticleSystem *clone() override;
void draw(Graphics *gfx, const Matrix4 &m) override;
private:
void drawInternal() const override;
}; // ParticleSystem }; // ParticleSystem
+4 -4
View File
@@ -855,14 +855,14 @@ void Shader::updateBuiltinUniforms()
// Only upload the matrices if they've changed. // Only upload the matrices if they've changed.
if (memcmp(curxform.getElements(), lastTransformMatrix.getElements(), sizeof(float) * 16) != 0) if (memcmp(curxform.getElements(), lastTransformMatrix.getElements(), sizeof(float) * 16) != 0)
{ {
GLint location = builtinUniforms[BUILTIN_MATRIX_TRANSFORM]; GLint location = builtinUniforms[BUILTIN_MATRIX_VIEW_FROM_LOCAL];
if (location >= 0) if (location >= 0)
glUniformMatrix4fv(location, 1, GL_FALSE, curxform.getElements()); glUniformMatrix4fv(location, 1, GL_FALSE, curxform.getElements());
// Also upload the re-calculated normal matrix, if possible. The normal // Also upload the re-calculated normal matrix, if possible. The normal
// matrix is the transpose of the inverse of the rotation portion // matrix is the transpose of the inverse of the rotation portion
// (top-left 3x3) of the transform matrix. // (top-left 3x3) of the transform matrix.
location = builtinUniforms[BUILTIN_MATRIX_NORMAL]; location = builtinUniforms[BUILTIN_MATRIX_VIEW_NORMAL_FROM_LOCAL];
if (location >= 0) if (location >= 0)
{ {
Matrix3 normalmatrix = Matrix3(curxform).transposedInverse(); Matrix3 normalmatrix = Matrix3(curxform).transposedInverse();
@@ -875,7 +875,7 @@ void Shader::updateBuiltinUniforms()
if (memcmp(curproj.getElements(), lastProjectionMatrix.getElements(), sizeof(float) * 16) != 0) if (memcmp(curproj.getElements(), lastProjectionMatrix.getElements(), sizeof(float) * 16) != 0)
{ {
GLint location = builtinUniforms[BUILTIN_MATRIX_PROJECTION]; GLint location = builtinUniforms[BUILTIN_MATRIX_CLIP_FROM_VIEW];
if (location >= 0) if (location >= 0)
glUniformMatrix4fv(location, 1, GL_FALSE, curproj.getElements()); glUniformMatrix4fv(location, 1, GL_FALSE, curproj.getElements());
@@ -885,7 +885,7 @@ void Shader::updateBuiltinUniforms()
if (tpmatrixneedsupdate) if (tpmatrixneedsupdate)
{ {
GLint location = builtinUniforms[BUILTIN_MATRIX_TRANSFORM_PROJECTION]; GLint location = builtinUniforms[BUILTIN_MATRIX_CLIP_FROM_LOCAL];
if (location >= 0) if (location >= 0)
{ {
Matrix4 tp_matrix(curproj, curxform); Matrix4 tp_matrix(curproj, curxform);
+9 -56
View File
@@ -51,52 +51,15 @@ SpriteBatch::~SpriteBatch()
{ {
} }
void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m) void SpriteBatch::drawInternal(vertex::CommonFormat format, size_t indexbytestart, size_t indexcount)
{ {
using namespace vertex;
if (next == 0)
return;
gfx->flushStreamDraws();
if (texture.get())
{
if (Shader::isDefaultActive())
{
Shader::StandardShader defaultshader = Shader::STANDARD_DEFAULT;
if (texture->getTextureType() == TEXTURE_2D_ARRAY)
defaultshader = Shader::STANDARD_ARRAY;
Shader::attachDefault(defaultshader);
}
if (Shader::current)
Shader::current->checkMainTexture(texture);
}
OpenGL::TempDebugGroup debuggroup("SpriteBatch draw"); OpenGL::TempDebugGroup debuggroup("SpriteBatch draw");
Graphics::TempTransform transform(gfx, m);
gl.bindTextureToUnit(texture, 0, false);
// Make sure the VBO isn't mapped when we draw (sends data to GPU if needed.)
array_buf->unmap();
CommonFormat format = vertex_format;
if (!color_active)
{
if (format == CommonFormat::XYf_STPf_RGBAub)
format = CommonFormat::XYf_STPf;
else
format = CommonFormat::XYf_STf;
}
uint32 enabledattribs = getFormatFlags(format); uint32 enabledattribs = getFormatFlags(format);
gl.setVertexPointers(format, array_buf, format_stride, 0); // We want attached attributes to override local attributes, so we should
// call this before binding attached attributes.
gl.setVertexPointers(format, array_buf, vertex_stride, 0);
for (const auto &it : attached_attributes) for (const auto &it : attached_attributes)
{ {
@@ -114,26 +77,16 @@ void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m)
} }
gl.useVertexAttribArrays(enabledattribs); gl.useVertexAttribArrays(enabledattribs);
gl.bindTextureToUnit(texture, 0, false);
gl.prepareDraw(); gl.prepareDraw();
int start = std::min(std::max(0, range_start), next - 1); gl.bindBuffer(BUFFER_INDEX, (GLuint) quad_indices.getBuffer()->getHandle());
int count = next; const void *indices = BUFFER_OFFSET(indexbytestart);
if (range_count > 0) GLenum gltype = OpenGL::getGLIndexDataType(quad_indices.getType());
count = std::min(count, range_count);
count = std::min(count, next - start); gl.drawElements(GL_TRIANGLES, (GLsizei) indexcount, gltype, indices);
if (count > 0)
{
gl.bindBuffer(BUFFER_INDEX, (GLuint) quad_indices.getBuffer()->getHandle());
const void *indices = BUFFER_OFFSET(start * quad_indices.getElementSize());
GLenum gltype = OpenGL::getGLIndexDataType(quad_indices.getType());
gl.drawElements(GL_TRIANGLES, (GLsizei) quad_indices.getIndexCount(count), gltype, indices);
}
} }
} // opengl } // opengl
+3 -2
View File
@@ -37,8 +37,9 @@ public:
SpriteBatch(Graphics *gfx, Texture *texture, int size, vertex::Usage usage); SpriteBatch(Graphics *gfx, Texture *texture, int size, vertex::Usage usage);
virtual ~SpriteBatch(); virtual ~SpriteBatch();
// Implements Drawable. protected:
void draw(Graphics *gfx, const Matrix4 &m) override;
void drawInternal(vertex::CommonFormat format, size_t indexbytestart, size_t indexcount) override;
}; // SpriteBatch }; // SpriteBatch
+2 -30
View File
@@ -40,36 +40,10 @@ Text::~Text()
{ {
} }
void Text::draw(Graphics *gfx, const Matrix4 &m) void Text::drawInternal(const std::vector<Font::DrawCommand> &commands) const
{ {
if (vbo == nullptr || draw_commands.empty())
return;
gfx->flushStreamDraws();
if (Shader::isDefaultActive())
Shader::attachDefault(Shader::STANDARD_DEFAULT);
if (Shader::current)
Shader::current->checkMainTextureType(TEXTURE_2D, false);
OpenGL::TempDebugGroup debuggroup("Text object draw"); OpenGL::TempDebugGroup debuggroup("Text object draw");
// Re-generate the text if the Font's texture cache was invalidated.
if (font->getTextureCacheID() != texture_cache_id)
regenerateVertices();
int totalverts = 0;
for (const Font::DrawCommand &cmd : draw_commands)
totalverts = std::max(cmd.startvertex + cmd.vertexcount, totalverts);
if ((size_t) totalverts / 4 > quadIndices.getSize())
quadIndices = QuadIndices(gfx, (size_t) totalverts / 4);
vbo->unmap(); // Make sure all pending data is flushed to the GPU.
Graphics::TempTransform transform(gfx, m);
gl.prepareDraw(); gl.prepareDraw();
gl.setVertexPointers(Font::vertexFormat, vbo, 0); gl.setVertexPointers(Font::vertexFormat, vbo, 0);
@@ -82,14 +56,12 @@ void Text::draw(Graphics *gfx, const Matrix4 &m)
// We need a separate draw call for every section of the text which uses a // We need a separate draw call for every section of the text which uses a
// different texture than the previous section. // different texture than the previous section.
for (const Font::DrawCommand &cmd : draw_commands) for (const Font::DrawCommand &cmd : commands)
{ {
GLsizei count = (cmd.vertexcount / 4) * 6; GLsizei count = (cmd.vertexcount / 4) * 6;
size_t offset = (cmd.startvertex / 4) * 6 * elemsize; size_t offset = (cmd.startvertex / 4) * 6 * elemsize;
// TODO: Use glDrawElementsBaseVertex when supported?
gl.bindTextureToUnit(cmd.texture, 0, false); gl.bindTextureToUnit(cmd.texture, 0, false);
gl.drawElements(GL_TRIANGLES, count, gltype, BUFFER_OFFSET(offset)); gl.drawElements(GL_TRIANGLES, count, gltype, BUFFER_OFFSET(offset));
} }
} }
+3 -2
View File
@@ -38,8 +38,9 @@ public:
Text(love::graphics::Graphics *gfx, love::graphics::Font *font, const std::vector<Font::ColoredString> &text = {}); Text(love::graphics::Graphics *gfx, love::graphics::Font *font, const std::vector<Font::ColoredString> &text = {});
virtual ~Text(); virtual ~Text();
// Implements Drawable. protected:
void draw(love::graphics::Graphics *gfx, const Matrix4 &m) override;
void drawInternal(const std::vector<Font::DrawCommand> &commands) const override;
}; // Text }; // Text
+1 -1
View File
@@ -22,7 +22,7 @@
// LOVE // LOVE
#include "common/int.h" #include "common/int.h"
#include "Color.h" #include "common/Color.h"
// C // C
#include <stddef.h> #include <stddef.h>
+1 -1
View File
@@ -46,7 +46,7 @@ int w_Canvas_renderTo(lua_State *L)
if (rt.canvas->getTextureType() != TEXTURE_2D) if (rt.canvas->getTextureType() != TEXTURE_2D)
{ {
rt.slice = (int) luaL_checknumber(L, 2) - 1; rt.slice = (int) luaL_checkinteger(L, 2) - 1;
startidx++; startidx++;
} }
+160 -80
View File
@@ -24,6 +24,7 @@
#include "image/ImageData.h" #include "image/ImageData.h"
#include "image/Image.h" #include "image/Image.h"
#include "font/Rasterizer.h" #include "font/Rasterizer.h"
#include "filesystem/Filesystem.h"
#include "filesystem/wrap_Filesystem.h" #include "filesystem/wrap_Filesystem.h"
#include "video/VideoStream.h" #include "video/VideoStream.h"
#include "image/wrap_Image.h" #include "image/wrap_Image.h"
@@ -321,7 +322,7 @@ int w_setCanvas(lua_State *L)
if (i == 1 && type != TEXTURE_2D) if (i == 1 && type != TEXTURE_2D)
{ {
target.slice = (int) luaL_checknumber(L, i + 1) - 1; target.slice = (int) luaL_checkinteger(L, i + 1) - 1;
target.mipmap = (int) luaL_optinteger(L, i + 2, 1) - 1; target.mipmap = (int) luaL_optinteger(L, i + 2, 1) - 1;
targets.colors.push_back(target); targets.colors.push_back(target);
break; break;
@@ -439,8 +440,54 @@ static void screenshotCallback(love::image::ImageData *i, Reference *ref, void *
delete ref; delete ref;
} }
static int screenshotSaveToFile(lua_State *L)
{
image::ImageData *id = image::luax_checkimagedata(L, 1);
const char *filename = luaL_checkstring(L, lua_upvalueindex(1));
const char *ext = luaL_checkstring(L, lua_upvalueindex(2));
image::FormatHandler::EncodedFormat format;
if (!image::ImageData::getConstant(ext, format))
return 0;
try
{
id->encode(format, filename, true);
}
catch (love::Exception &e)
{
printf("Screenshot encoding or saving failed: %s", e.what());
// Do nothing...
}
return 0;
}
int w_captureScreenshot(lua_State *L) int w_captureScreenshot(lua_State *L)
{ {
if (lua_isstring(L, 1))
{
std::string filename = luax_checkstring(L, 1);
std::string ext;
size_t dotpos = filename.rfind('.');
if (dotpos != std::string::npos)
ext = filename.substr(dotpos + 1);
std::transform(ext.begin(), ext.end(), ext.begin(), tolower);
image::FormatHandler::EncodedFormat format;
if (!image::ImageData::getConstant(ext.c_str(), format))
return luaL_error(L, "Invalid encoded image format: %s", ext.c_str());
lua_pushvalue(L, 1);
luax_pushstring(L, ext);
lua_pushcclosure(L, screenshotSaveToFile, 2);
lua_replace(L, 1);
}
luaL_checktype(L, 1, LUA_TFUNCTION); luaL_checktype(L, 1, LUA_TFUNCTION);
Graphics::ScreenshotInfo info; Graphics::ScreenshotInfo info;
@@ -470,10 +517,10 @@ int w_setScissor(lua_State *L)
} }
Rect rect; Rect rect;
rect.x = (int) luaL_checknumber(L, 1); rect.x = (int) luaL_checkinteger(L, 1);
rect.y = (int) luaL_checknumber(L, 2); rect.y = (int) luaL_checkinteger(L, 2);
rect.w = (int) luaL_checknumber(L, 3); rect.w = (int) luaL_checkinteger(L, 3);
rect.h = (int) luaL_checknumber(L, 4); rect.h = (int) luaL_checkinteger(L, 4);
if (rect.w < 0 || rect.h < 0) if (rect.w < 0 || rect.h < 0)
return luaL_error(L, "Can't set scissor with negative width and/or height."); return luaL_error(L, "Can't set scissor with negative width and/or height.");
@@ -485,10 +532,10 @@ int w_setScissor(lua_State *L)
int w_intersectScissor(lua_State *L) int w_intersectScissor(lua_State *L)
{ {
Rect rect; Rect rect;
rect.x = (int) luaL_checknumber(L, 1); rect.x = (int) luaL_checkinteger(L, 1);
rect.y = (int) luaL_checknumber(L, 2); rect.y = (int) luaL_checkinteger(L, 2);
rect.w = (int) luaL_checknumber(L, 3); rect.w = (int) luaL_checkinteger(L, 3);
rect.h = (int) luaL_checknumber(L, 4); rect.h = (int) luaL_checkinteger(L, 4);
if (rect.w < 0 || rect.h < 0) if (rect.w < 0 || rect.h < 0)
return luaL_error(L, "Can't set scissor with negative width and/or height."); return luaL_error(L, "Can't set scissor with negative width and/or height.");
@@ -524,7 +571,7 @@ int w_stencil(lua_State *L)
return luaL_error(L, "Invalid stencil draw action: %s", actionstr); return luaL_error(L, "Invalid stencil draw action: %s", actionstr);
} }
int stencilvalue = (int) luaL_optnumber(L, 3, 1); int stencilvalue = (int) luaL_optinteger(L, 3, 1);
// Fourth argument: whether to keep the contents of the stencil buffer. // Fourth argument: whether to keep the contents of the stencil buffer.
OptionalInt stencilclear; OptionalInt stencilclear;
@@ -561,7 +608,7 @@ int w_setStencilTest(lua_State *L)
if (!getConstant(comparestr, compare)) if (!getConstant(comparestr, compare))
return luaL_error(L, "Invalid compare mode: %s", comparestr); return luaL_error(L, "Invalid compare mode: %s", comparestr);
comparevalue = (int) luaL_checknumber(L, 2); comparevalue = (int) luaL_checkinteger(L, 2);
} }
luax_catchexcept(L, [&](){ instance()->setStencilTest(compare, comparevalue); }); luax_catchexcept(L, [&](){ instance()->setStencilTest(compare, comparevalue); });
@@ -942,14 +989,14 @@ int w_newQuad(lua_State *L)
} }
else if (luax_istype(L, 6, Texture::type)) else if (luax_istype(L, 6, Texture::type))
{ {
layer = (int) luaL_checknumber(L, 5) - 1; layer = (int) luaL_checkinteger(L, 5) - 1;
Texture *texture = luax_checktexture(L, 6); Texture *texture = luax_checktexture(L, 6);
sw = texture->getWidth(); sw = texture->getWidth();
sh = texture->getHeight(); sh = texture->getHeight();
} }
else if (!lua_isnoneornil(L, 7)) else if (!lua_isnoneornil(L, 7))
{ {
layer = (int) luaL_checknumber(L, 5) - 1; layer = (int) luaL_checkinteger(L, 5) - 1;
sw = luaL_checknumber(L, 6); sw = luaL_checknumber(L, 6);
sh = luaL_checknumber(L, 7); sh = luaL_checknumber(L, 7);
} }
@@ -1030,7 +1077,7 @@ int w_newSpriteBatch(lua_State *L)
luax_checkgraphicscreated(L); luax_checkgraphicscreated(L);
Texture *texture = luax_checktexture(L, 1); Texture *texture = luax_checktexture(L, 1);
int size = (int) luaL_optnumber(L, 2, 1000); int size = (int) luaL_optinteger(L, 2, 1000);
vertex::Usage usage = vertex::USAGE_DYNAMIC; vertex::Usage usage = vertex::USAGE_DYNAMIC;
if (lua_gettop(L) > 2) if (lua_gettop(L) > 2)
{ {
@@ -1075,8 +1122,8 @@ int w_newCanvas(lua_State *L)
Canvas::Settings settings; Canvas::Settings settings;
// check if width and height are given. else default to screen dimensions. // check if width and height are given. else default to screen dimensions.
settings.width = (int) luaL_optnumber(L, 1, instance()->getWidth()); settings.width = (int) luaL_optinteger(L, 1, instance()->getWidth());
settings.height = (int) luaL_optnumber(L, 2, instance()->getHeight()); settings.height = (int) luaL_optinteger(L, 2, instance()->getHeight());
// Default to the screen's current pixel density scale. // Default to the screen's current pixel density scale.
settings.pixeldensity = instance()->getScreenPixelDensity(); settings.pixeldensity = instance()->getScreenPixelDensity();
@@ -1085,7 +1132,7 @@ int w_newCanvas(lua_State *L)
if (lua_isnumber(L, 3)) if (lua_isnumber(L, 3))
{ {
settings.layers = (int) luaL_checknumber(L, 3); settings.layers = (int) luaL_checkinteger(L, 3);
settings.type = TEXTURE_2D_ARRAY; settings.type = TEXTURE_2D_ARRAY;
startidx = 4; startidx = 4;
} }
@@ -1142,36 +1189,48 @@ int w_newCanvas(lua_State *L)
static int w_getShaderSource(lua_State *L, int startidx, bool gles, Shader::ShaderSource &source) static int w_getShaderSource(lua_State *L, int startidx, bool gles, Shader::ShaderSource &source)
{ {
using namespace love::filesystem;
luax_checkgraphicscreated(L); luax_checkgraphicscreated(L);
auto fs = Module::getInstance<Filesystem>(Module::M_FILESYSTEM);
// read any filepath arguments // read any filepath arguments
for (int i = startidx; i < startidx + 2; i++) for (int i = startidx; i < startidx + 2; i++)
{ {
if (!lua_isstring(L, i)) if (!lua_isstring(L, i))
continue;
// call love.filesystem.isFile(arg_i)
luax_getfunction(L, "filesystem", "isFile");
lua_pushvalue(L, i);
lua_call(L, 1, 1);
bool isFile = luax_toboolean(L, -1);
lua_pop(L, 1);
if (isFile)
{ {
luax_getfunction(L, "filesystem", "read"); if (luax_cangetfiledata(L, i))
lua_pushvalue(L, i); {
lua_call(L, 1, 1); FileData *fd = luax_getfiledata(L, i);
lua_pushlstring(L, (const char *) fd->getData(), fd->getSize());
fd->release();
lua_replace(L, i);
}
continue;
}
size_t slen = 0;
const char *str = lua_tolstring(L, i, &slen);
if (fs != nullptr && fs->isFile(str))
{
FileData *fd = nullptr;
luax_catchexcept(L, [&](){ fd = fs->read(str); });
lua_pushlstring(L, (const char *) fd->getData(), fd->getSize());
fd->release();
lua_replace(L, i); lua_replace(L, i);
} }
else else
{ {
// Check if the argument looks like a filepath - we want a nicer // Check if the argument looks like a filepath - we want a nicer
// error for misspelled filepath arguments. // error for misspelled filepath arguments.
size_t slen = 0; if (slen > 0 && slen < 64 && !strchr(str, '\n'))
const char *str = lua_tolstring(L, i, &slen);
if (slen > 0 && slen < 256 && !strchr(str, '\n'))
{ {
const char *ext = strchr(str, '.'); const char *ext = strchr(str, '.');
if (ext != nullptr && !strchr(ext, ';') && !strchr(ext, ' ')) if (ext != nullptr && !strchr(ext, ';') && !strchr(ext, ' '))
@@ -1352,7 +1411,7 @@ static Mesh *newStandardMesh(lua_State *L)
} }
else else
{ {
int count = (int) luaL_checknumber(L, 1); int count = (int) luaL_checkinteger(L, 1);
luax_catchexcept(L, [&](){ t = instance()->newMesh(count, drawmode, usage); }); luax_catchexcept(L, [&](){ t = instance()->newMesh(count, drawmode, usage); });
} }
@@ -1397,7 +1456,7 @@ static Mesh *newCustomMesh(lua_State *L)
return nullptr; return nullptr;
} }
format.components = (int) luaL_checknumber(L, -1); format.components = (int) luaL_checkinteger(L, -1);
if (format.components <= 0 || format.components > 4) if (format.components <= 0 || format.components > 4)
{ {
luaL_error(L, "Number of vertex attribute components must be between 1 and 4 (got %d)", format.components); luaL_error(L, "Number of vertex attribute components must be between 1 and 4 (got %d)", format.components);
@@ -1410,7 +1469,7 @@ static Mesh *newCustomMesh(lua_State *L)
if (lua_isnumber(L, 2)) if (lua_isnumber(L, 2))
{ {
int vertexcount = (int) luaL_checknumber(L, 2); int vertexcount = (int) luaL_checkinteger(L, 2);
luax_catchexcept(L, [&](){ t = instance()->newMesh(vertexformat, vertexcount, drawmode, usage); }); luax_catchexcept(L, [&](){ t = instance()->newMesh(vertexformat, vertexcount, drawmode, usage); });
} }
else if (luax_istype(L, 2, Data::type)) else if (luax_istype(L, 2, Data::type))
@@ -2073,6 +2132,9 @@ int w_getStats(lua_State *L)
lua_pushinteger(L, stats.drawCalls); lua_pushinteger(L, stats.drawCalls);
lua_setfield(L, -2, "drawcalls"); lua_setfield(L, -2, "drawcalls");
lua_pushinteger(L, stats.drawCallsBatched);
lua_setfield(L, -2, "drawcallsbatched");
lua_pushinteger(L, stats.canvasSwitches); lua_pushinteger(L, stats.canvasSwitches);
lua_setfield(L, -2, "canvasswitches"); lua_setfield(L, -2, "canvasswitches");
@@ -2135,7 +2197,7 @@ int w_drawLayer(lua_State *L)
{ {
Texture *texture = luax_checktexture(L, 1); Texture *texture = luax_checktexture(L, 1);
Quad *quad = nullptr; Quad *quad = nullptr;
int layer = (int) luaL_checknumber(L, 2) - 1; int layer = (int) luaL_checkinteger(L, 2) - 1;
int startidx = 3; int startidx = 3;
if (luax_istype(L, startidx, Quad::type)) if (luax_istype(L, startidx, Quad::type))
@@ -2279,23 +2341,23 @@ int w_points(lua_State *L)
if (args % 2 != 0 && !is_table_of_tables) if (args % 2 != 0 && !is_table_of_tables)
return luaL_error(L, "Number of vertex components must be a multiple of two"); return luaL_error(L, "Number of vertex components must be a multiple of two");
int numpoints = args / 2; int numpositions = args / 2;
if (is_table_of_tables) if (is_table_of_tables)
numpoints = args; numpositions = args;
float *coords = nullptr; Vector2 *positions = nullptr;
Colorf *colors = nullptr; Colorf *colors = nullptr;
if (is_table_of_tables) if (is_table_of_tables)
{ {
size_t datasize = (sizeof(float) * 2 + sizeof(Colorf)) * numpoints; size_t datasize = (sizeof(Vector2) + sizeof(Colorf)) * numpositions;
uint8 *data = instance()->getScratchBuffer<uint8>(datasize); uint8 *data = instance()->getScratchBuffer<uint8>(datasize);
coords = (float *) data; positions = (Vector2 *) data;
colors = (Colorf *) (data + sizeof(float) * numpoints * 2); colors = (Colorf *) (data + sizeof(Vector2) * numpositions);
} }
else else
coords = instance()->getScratchBuffer<float>(numpoints * 2); positions = instance()->getScratchBuffer<Vector2>(numpositions);
if (is_table) if (is_table)
{ {
@@ -2308,13 +2370,13 @@ int w_points(lua_State *L)
for (int j = 1; j <= 6; j++) for (int j = 1; j <= 6; j++)
lua_rawgeti(L, -j, j); lua_rawgeti(L, -j, j);
coords[i * 2 + 0] = luax_tofloat(L, -6); positions[i].x = luax_tofloat(L, -6);
coords[i * 2 + 1] = luax_tofloat(L, -5); positions[i].y = luax_tofloat(L, -5);
colors[i].r = luaL_optnumber(L, -4, 1.0); colors[i].r = (float) luaL_optnumber(L, -4, 1.0);
colors[i].g = luaL_optnumber(L, -3, 1.0); colors[i].g = (float) luaL_optnumber(L, -3, 1.0);
colors[i].b = luaL_optnumber(L, -2, 1.0); colors[i].b = (float) luaL_optnumber(L, -2, 1.0);
colors[i].a = luaL_optnumber(L, -1, 1.0); colors[i].a = (float) luaL_optnumber(L, -1, 1.0);
lua_pop(L, 7); lua_pop(L, 7);
} }
@@ -2322,21 +2384,26 @@ int w_points(lua_State *L)
else else
{ {
// points({x1, y1, x2, y2, ...}) // points({x1, y1, x2, y2, ...})
for (int i = 0; i < args; i++) for (int i = 0; i < numpositions; i++)
{ {
lua_rawgeti(L, 1, i + 1); lua_rawgeti(L, 1, i * 2 + 1);
coords[i] = luax_tofloat(L, -1); lua_rawgeti(L, 1, i * 2 + 2);
lua_pop(L, 1); positions[i].x = luax_tofloat(L, -2);
positions[i].y = luax_tofloat(L, -1);
lua_pop(L, 2);
} }
} }
} }
else else
{ {
for (int i = 0; i < args; i++) for (int i = 0; i < numpositions; i++)
coords[i] = luax_tofloat(L, i + 1); {
positions[i].x = luax_tofloat(L, i * 2 + 1);
positions[i].y = luax_tofloat(L, i * 2 + 2);
}
} }
luax_catchexcept(L, [&](){ instance()->points(coords, colors, numpoints); }); luax_catchexcept(L, [&](){ instance()->points(positions, colors, numpositions); });
return 0; return 0;
} }
@@ -2355,24 +2422,31 @@ int w_line(lua_State *L)
else if (args < 4) else if (args < 4)
return luaL_error(L, "Need at least two vertices to draw a line"); return luaL_error(L, "Need at least two vertices to draw a line");
float *coords = instance()->getScratchBuffer<float>(args); int numvertices = args / 2;
Vector2 *coords = instance()->getScratchBuffer<Vector2>(numvertices);
if (is_table) if (is_table)
{ {
for (int i = 0; i < args; ++i) for (int i = 0; i < numvertices; ++i)
{ {
lua_rawgeti(L, 1, i + 1); lua_rawgeti(L, 1, (i * 2) + 1);
coords[i] = luax_tofloat(L, -1); lua_rawgeti(L, 1, (i * 2) + 2);
lua_pop(L, 1); coords[i].x = luax_tofloat(L, -2);
coords[i].y = luax_tofloat(L, -1);
lua_pop(L, 2);
} }
} }
else else
{ {
for (int i = 0; i < args; ++i) for (int i = 0; i < numvertices; ++i)
coords[i] = luax_tofloat(L, i + 1); {
coords[i].x = luax_tofloat(L, (i * 2) + 1);
coords[i].y = luax_tofloat(L, (i * 2) + 2);
}
} }
luax_catchexcept(L, luax_catchexcept(L,
[&](){ instance()->polyline(coords, args); } [&](){ instance()->polyline(coords, numvertices); }
); );
return 0; return 0;
@@ -2403,7 +2477,7 @@ int w_rectangle(lua_State *L)
luax_catchexcept(L, [&](){ instance()->rectangle(mode, x, y, w, h, rx, ry); }); luax_catchexcept(L, [&](){ instance()->rectangle(mode, x, y, w, h, rx, ry); });
else else
{ {
int points = (int) luaL_checknumber(L, 8); int points = (int) luaL_checkinteger(L, 8);
luax_catchexcept(L, [&](){ instance()->rectangle(mode, x, y, w, h, rx, ry, points); }); luax_catchexcept(L, [&](){ instance()->rectangle(mode, x, y, w, h, rx, ry, points); });
} }
@@ -2425,7 +2499,7 @@ int w_circle(lua_State *L)
luax_catchexcept(L, [&](){ instance()->circle(mode, x, y, radius); }); luax_catchexcept(L, [&](){ instance()->circle(mode, x, y, radius); });
else else
{ {
int points = (int) luaL_checknumber(L, 5); int points = (int) luaL_checkinteger(L, 5);
luax_catchexcept(L, [&](){ instance()->circle(mode, x, y, radius, points); }); luax_catchexcept(L, [&](){ instance()->circle(mode, x, y, radius, points); });
} }
@@ -2448,7 +2522,7 @@ int w_ellipse(lua_State *L)
luax_catchexcept(L, [&](){ instance()->ellipse(mode, x, y, a, b); }); luax_catchexcept(L, [&](){ instance()->ellipse(mode, x, y, a, b); });
else else
{ {
int points = (int) luaL_checknumber(L, 6); int points = (int) luaL_checkinteger(L, 6);
luax_catchexcept(L, [&](){ instance()->ellipse(mode, x, y, a, b, points); }); luax_catchexcept(L, [&](){ instance()->ellipse(mode, x, y, a, b, points); });
} }
@@ -2485,7 +2559,7 @@ int w_arc(lua_State *L)
luax_catchexcept(L, [&](){ instance()->arc(drawmode, arcmode, x, y, radius, angle1, angle2); }); luax_catchexcept(L, [&](){ instance()->arc(drawmode, arcmode, x, y, radius, angle1, angle2); });
else else
{ {
int points = (int) luaL_checknumber(L, startidx + 5); int points = (int) luaL_checkinteger(L, startidx + 5);
luax_catchexcept(L, [&](){ instance()->arc(drawmode, arcmode, x, y, radius, angle1, angle2, points); }); luax_catchexcept(L, [&](){ instance()->arc(drawmode, arcmode, x, y, radius, angle1, angle2, points); });
} }
@@ -2513,28 +2587,34 @@ int w_polygon(lua_State *L)
else if (args < 6) else if (args < 6)
return luaL_error(L, "Need at least three vertices to draw a polygon"); return luaL_error(L, "Need at least three vertices to draw a polygon");
int numvertices = args / 2;
// fetch coords // fetch coords
float *coords = instance()->getScratchBuffer<float>(args + 2); Vector2 *coords = instance()->getScratchBuffer<Vector2>(numvertices + 1);
if (is_table) if (is_table)
{ {
for (int i = 0; i < args; ++i) for (int i = 0; i < numvertices; ++i)
{ {
lua_rawgeti(L, 2, i + 1); lua_rawgeti(L, 2, (i * 2) + 1);
coords[i] = luax_tofloat(L, -1); lua_rawgeti(L, 2, (i * 2) + 2);
lua_pop(L, 1); coords[i].x = luax_tofloat(L, -2);
coords[i].y = luax_tofloat(L, -1);
lua_pop(L, 2);
} }
} }
else else
{ {
for (int i = 0; i < args; ++i) for (int i = 0; i < numvertices; ++i)
coords[i] = luax_tofloat(L, i + 2); {
coords[i].x = luax_tofloat(L, (i * 2) + 2);
coords[i].y = luax_tofloat(L, (i * 2) + 3);
}
} }
// make a closed loop // make a closed loop
coords[args] = coords[0]; coords[numvertices] = coords[0];
coords[args+1] = coords[1];
luax_catchexcept(L, [&](){ instance()->polygon(mode, coords, args+2); }); luax_catchexcept(L, [&](){ instance()->polygon(mode, coords, numvertices+1); });
return 0; return 0;
} }
+16 -9
View File
@@ -72,11 +72,18 @@ GLSL.UNIFORMS = [[
// According to the GLSL ES 1.0 spec, uniform precision must match between stages, // According to the GLSL ES 1.0 spec, uniform precision must match between stages,
// but we can't guarantee that highp is always supported in fragment shaders... // but we can't guarantee that highp is always supported in fragment shaders...
// We *really* don't want to use mediump for these in vertex shaders though. // We *really* don't want to use mediump for these in vertex shaders though.
uniform LOVE_HIGHP_OR_MEDIUMP mat4 TransformMatrix; uniform LOVE_HIGHP_OR_MEDIUMP mat4 ViewSpaceFromLocal;
uniform LOVE_HIGHP_OR_MEDIUMP mat4 ProjectionMatrix; uniform LOVE_HIGHP_OR_MEDIUMP mat4 ClipSpaceFromView;
uniform LOVE_HIGHP_OR_MEDIUMP mat4 TransformProjectionMatrix; uniform LOVE_HIGHP_OR_MEDIUMP mat4 ClipSpaceFromLocal;
uniform LOVE_HIGHP_OR_MEDIUMP mat3 NormalMatrix; uniform LOVE_HIGHP_OR_MEDIUMP mat3 ViewNormalFromLocal;
uniform LOVE_HIGHP_OR_MEDIUMP vec4 love_ScreenSize;]] uniform LOVE_HIGHP_OR_MEDIUMP vec4 love_ScreenSize;
// Compatibility
#define TransformMatrix ViewSpaceFromLocal
#define ProjectionMatrix ClipSpaceFromView
#define TransformProjectionMatrix ClipSpaceFromLocal
#define NormalMatrix ViewNormalFromLocal
]]
GLSL.FUNCTIONS = [[ GLSL.FUNCTIONS = [[
#ifdef GL_ES #ifdef GL_ES
@@ -222,13 +229,13 @@ attribute vec4 ConstantColor;
varying vec4 VaryingTexCoord; varying vec4 VaryingTexCoord;
varying vec4 VaryingColor; varying vec4 VaryingColor;
vec4 position(mat4 transform_proj, vec4 vertpos); vec4 position(mat4 clipSpaceFromLocal, vec4 localPosition);
void main() { void main() {
VaryingTexCoord = VertexTexCoord; VaryingTexCoord = VertexTexCoord;
VaryingColor = gammaCorrectColor(VertexColor) * ConstantColor; VaryingColor = gammaCorrectColor(VertexColor) * ConstantColor;
setPointSize(); setPointSize();
love_Position = position(TransformProjectionMatrix, VertexPosition); love_Position = position(ClipSpaceFromLocal, VertexPosition);
}]], }]],
} }
@@ -424,8 +431,8 @@ end
local defaultcode = { local defaultcode = {
vertex = [[ vertex = [[
vec4 position(mat4 transform_proj, vec4 vertpos) { vec4 position(mat4 clipSpaceFromLocal, vec4 localPosition) {
return transform_proj * vertpos; return clipSpaceFromLocal * localPosition;
}]], }]],
pixel = [[ pixel = [[
vec4 effect(vec4 vcolor, Image tex, vec2 texcoord, vec2 pixcoord) { vec4 effect(vec4 vcolor, Image tex, vec2 texcoord, vec2 pixcoord) {
+3 -3
View File
@@ -56,12 +56,12 @@ int w_Image_replacePixels(lua_State *L)
if (i->getTextureType() != TEXTURE_2D) if (i->getTextureType() != TEXTURE_2D)
{ {
slice = (int) luaL_checknumber(L, 3) - 1; slice = (int) luaL_checkinteger(L, 3) - 1;
if (!reloadmipmaps) if (!reloadmipmaps)
mipmap = (int) luaL_optnumber(L, 4, 1) - 1; mipmap = (int) luaL_optinteger(L, 4, 1) - 1;
} }
else if (!reloadmipmaps) else if (!reloadmipmaps)
mipmap = (int) luaL_optnumber(L, 3, 1) - 1; mipmap = (int) luaL_optinteger(L, 3, 1) - 1;
luax_catchexcept(L, [&](){ i->replacePixels(id, slice, mipmap, reloadmipmaps); }); luax_catchexcept(L, [&](){ i->replacePixels(id, slice, mipmap, reloadmipmaps); });
return 0; return 0;
+3 -3
View File
@@ -386,7 +386,7 @@ int w_Mesh_setVertexMap(lua_State *L)
size_t datatypesize = vertex::getIndexDataSize(indextype); size_t datatypesize = vertex::getIndexDataSize(indextype);
int indexcount = (int) luaL_optnumber(L, 4, d->getSize() / datatypesize); int indexcount = (int) luaL_optinteger(L, 4, d->getSize() / datatypesize);
if (indexcount < 1 || indexcount * datatypesize > d->getSize()) if (indexcount < 1 || indexcount * datatypesize > d->getSize())
return luaL_error(L, "Invalid index count: %d", indexcount); return luaL_error(L, "Invalid index count: %d", indexcount);
@@ -515,8 +515,8 @@ int w_Mesh_setDrawRange(lua_State *L)
t->setDrawRange(); t->setDrawRange();
else else
{ {
int start = (int) luaL_checknumber(L, 2) - 1; int start = (int) luaL_checkinteger(L, 2) - 1;
int count = (int) luaL_checknumber(L, 3); int count = (int) luaL_checkinteger(L, 3);
luax_catchexcept(L, [&](){ t->setDrawRange(start, count); }); luax_catchexcept(L, [&](){ t->setDrawRange(start, count); });
} }
+1 -1
View File
@@ -699,7 +699,7 @@ int w_ParticleSystem_reset(lua_State *L)
int w_ParticleSystem_emit(lua_State *L) int w_ParticleSystem_emit(lua_State *L)
{ {
ParticleSystem *t = luax_checkparticlesystem(L, 1); ParticleSystem *t = luax_checkparticlesystem(L, 1);
int num = (int) luaL_checknumber(L, 2); int num = (int) luaL_checkinteger(L, 2);
t->emit(num); t->emit(num);
return 0; return 0;
} }
+1 -1
View File
@@ -77,7 +77,7 @@ int w_Quad_getTextureDimensions(lua_State *L)
int w_Quad_setLayer(lua_State *L) int w_Quad_setLayer(lua_State *L)
{ {
Quad *quad = luax_checkquad(L, 1); Quad *quad = luax_checkquad(L, 1);
int layer = (int) luaL_checknumber(L, 2) - 1; int layer = (int) luaL_checkinteger(L, 2) - 1;
quad->setLayer(layer); quad->setLayer(layer);
return 0; return 0;
} }
+5 -5
View File
@@ -63,7 +63,7 @@ static inline int w_SpriteBatch_add_or_set(lua_State *L, SpriteBatch *t, int sta
static int w_SpriteBatch_addLayer_or_setLayer(lua_State *L, SpriteBatch *t, int startidx, int index) static int w_SpriteBatch_addLayer_or_setLayer(lua_State *L, SpriteBatch *t, int startidx, int index)
{ {
Quad *quad = nullptr; Quad *quad = nullptr;
int layer = (int) luaL_checknumber(L, startidx) - 1; int layer = (int) luaL_checkinteger(L, startidx) - 1;
startidx++; startidx++;
if (luax_istype(L, startidx, Quad::type)) if (luax_istype(L, startidx, Quad::type))
@@ -101,7 +101,7 @@ int w_SpriteBatch_add(lua_State *L)
int w_SpriteBatch_set(lua_State *L) int w_SpriteBatch_set(lua_State *L)
{ {
SpriteBatch *t = luax_checkspritebatch(L, 1); SpriteBatch *t = luax_checkspritebatch(L, 1);
int index = (int) luaL_checknumber(L, 2) - 1; int index = (int) luaL_checkinteger(L, 2) - 1;
w_SpriteBatch_add_or_set(L, t, 3, index); w_SpriteBatch_add_or_set(L, t, 3, index);
@@ -121,7 +121,7 @@ int w_SpriteBatch_addLayer(lua_State *L)
int w_SpriteBatch_setLayer(lua_State *L) int w_SpriteBatch_setLayer(lua_State *L)
{ {
SpriteBatch *t = luax_checkspritebatch(L, 1); SpriteBatch *t = luax_checkspritebatch(L, 1);
int index = (int) luaL_checknumber(L, 2) - 1; int index = (int) luaL_checkinteger(L, 2) - 1;
w_SpriteBatch_addLayer_or_setLayer(L, t, 3, index); w_SpriteBatch_addLayer_or_setLayer(L, t, 3, index);
@@ -251,8 +251,8 @@ int w_SpriteBatch_setDrawRange(lua_State *L)
t->setDrawRange(); t->setDrawRange();
else else
{ {
int start = (int) luaL_checknumber(L, 2) - 1; int start = (int) luaL_checkinteger(L, 2) - 1;
int count = (int) luaL_checknumber(L, 3); int count = (int) luaL_checkinteger(L, 3);
luax_catchexcept(L, [&](){ t->setDrawRange(start, count); }); luax_catchexcept(L, [&](){ t->setDrawRange(start, count); });
} }
+3 -3
View File
@@ -183,7 +183,7 @@ int w_Text_getFont(lua_State *L)
int w_Text_getWidth(lua_State *L) int w_Text_getWidth(lua_State *L)
{ {
Text *t = luax_checktext(L, 1); Text *t = luax_checktext(L, 1);
int index = (int) luaL_optnumber(L, 2, 0) - 1; int index = (int) luaL_optinteger(L, 2, 0) - 1;
lua_pushnumber(L, t->getWidth(index)); lua_pushnumber(L, t->getWidth(index));
return 1; return 1;
} }
@@ -191,7 +191,7 @@ int w_Text_getWidth(lua_State *L)
int w_Text_getHeight(lua_State *L) int w_Text_getHeight(lua_State *L)
{ {
Text *t = luax_checktext(L, 1); Text *t = luax_checktext(L, 1);
int index = (int) luaL_optnumber(L, 2, 0) - 1; int index = (int) luaL_optinteger(L, 2, 0) - 1;
lua_pushnumber(L, t->getHeight(index)); lua_pushnumber(L, t->getHeight(index));
return 1; return 1;
} }
@@ -199,7 +199,7 @@ int w_Text_getHeight(lua_State *L)
int w_Text_getDimensions(lua_State *L) int w_Text_getDimensions(lua_State *L)
{ {
Text *t = luax_checktext(L, 1); Text *t = luax_checktext(L, 1);
int index = (int) luaL_optnumber(L, 2, 0) - 1; int index = (int) luaL_optinteger(L, 2, 0) - 1;
lua_pushnumber(L, t->getWidth(index)); lua_pushnumber(L, t->getWidth(index));
lua_pushnumber(L, t->getHeight(index)); lua_pushnumber(L, t->getHeight(index));
return 2; return 2;
@@ -18,20 +18,17 @@
* 3. This notice may not be removed or altered from any source distribution. * 3. This notice may not be removed or altered from any source distribution.
**/ **/
#ifndef LOVE_IMAGE_MAGPIE_COMPRESSED_HANDLER_H #pragma once
#define LOVE_IMAGE_MAGPIE_COMPRESSED_HANDLER_H
// LOVE // LOVE
#include "filesystem/FileData.h"
#include "image/CompressedImageData.h"
#include "common/Object.h" #include "common/Object.h"
#include "filesystem/FileData.h"
#include "CompressedSlice.h"
namespace love namespace love
{ {
namespace image namespace image
{ {
namespace magpie
{
/** /**
* Base class for all CompressedImageData parser library interfaces. * Base class for all CompressedImageData parser library interfaces.
@@ -45,8 +42,8 @@ public:
virtual ~CompressedFormatHandler() {} virtual ~CompressedFormatHandler() {}
/** /**
* Determines whether a particular FileData can be parsed as CompressedImageData * Determines whether a particular FileData can be parsed as
* by this handler. * CompressedImageData by this handler.
* @param data The data to parse. * @param data The data to parse.
**/ **/
virtual bool canParse(const filesystem::FileData *data) = 0; virtual bool canParse(const filesystem::FileData *data) = 0;
@@ -56,21 +53,18 @@ public:
* a single block of memory containing all the images. * a single block of memory containing all the images.
* *
* @param[in] filedata The data to parse. * @param[in] filedata The data to parse.
* @param[out] images The list of sub-images generated. Byte data is a pointer * @param[out] images The list of sub-images generated. Byte data is a
* to the returned data. * pointer to the returned data.
* @param[out] format The format of the Compressed Data. * @param[out] format The format of the Compressed Data.
* @param[out] sRGB Whether the texture is sRGB-encoded. * @param[out] sRGB Whether the texture is sRGB-encoded.
* *
* @return The single block of memory containing the parsed images. * @return The single block of memory containing the parsed images.
**/ **/
virtual StrongRef<CompressedImageData::Memory> parse(filesystem::FileData *filedata, virtual StrongRef<CompressedMemory> parse(filesystem::FileData *filedata,
std::vector<StrongRef<CompressedImageData::Slice>> &images, std::vector<StrongRef<CompressedSlice>> &images,
PixelFormat &format, bool &sRGB) = 0; PixelFormat &format, bool &sRGB) = 0;
}; // CompressedFormatHandler }; // CompressedFormatHandler
} // magpie
} // image } // image
} // love } // love
#endif // LOVE_IMAGE_MAGPIE_COMPRESSED_HANDLER_H
+46 -50
View File
@@ -27,58 +27,54 @@ namespace image
love::Type CompressedImageData::type("CompressedImageData", &Data::type); love::Type CompressedImageData::type("CompressedImageData", &Data::type);
CompressedImageData::Memory::Memory(size_t size) CompressedImageData::CompressedImageData(const std::list<CompressedFormatHandler *> &formats, love::filesystem::FileData *filedata)
: data(nullptr)
, size(size)
{
try
{
data = new uint8[size];
}
catch (std::exception &)
{
throw love::Exception("Out of memory.");
}
}
CompressedImageData::Memory::~Memory()
{
delete[] data;
}
CompressedImageData::Slice::Slice(PixelFormat format, int width, int height, Memory *memory, size_t offset, size_t size)
: memory(memory)
, offset(offset)
, dataSize(size)
{
this->format = format;
this->width = width;
this->height = height;
}
CompressedImageData::Slice::Slice(const Slice &s)
: memory(s.memory)
, offset(s.offset)
, dataSize(s.dataSize)
{
this->format = s.getFormat();
this->width = s.getWidth();
this->height = s.getHeight();
}
CompressedImageData::Slice::~Slice()
{
}
CompressedImageData::Slice *CompressedImageData::Slice::clone() const
{
return new Slice(*this);
}
CompressedImageData::CompressedImageData()
: format(PIXELFORMAT_UNKNOWN) : format(PIXELFORMAT_UNKNOWN)
, sRGB(false) , sRGB(false)
{ {
CompressedFormatHandler *parser = nullptr;
for (CompressedFormatHandler *handler : formats)
{
if (handler->canParse(filedata))
{
parser = handler;
break;
}
}
if (parser == nullptr)
throw love::Exception("Could not parse compressed data: Unknown format.");
memory = parser->parse(filedata, dataImages, format, sRGB);
if (memory == nullptr)
throw love::Exception("Could not parse compressed data.");
if (format == PIXELFORMAT_UNKNOWN)
throw love::Exception("Could not parse compressed data: Unknown format.");
if (dataImages.size() == 0 || memory->size == 0)
throw love::Exception("Could not parse compressed data: No valid data?");
}
CompressedImageData::CompressedImageData(const CompressedImageData &c)
: format(c.format)
, sRGB(c.sRGB)
{
memory.set(new CompressedMemory(c.memory->size), Acquire::NORETAIN);
memcpy(memory->data, c.memory->data, memory->size);
for (const auto &i : c.dataImages)
{
auto slice = new CompressedSlice(i->getFormat(), i->getWidth(), i->getHeight(), memory, i->getOffset(), i->getSize());
dataImages.push_back(slice);
slice->release();
}
}
CompressedImageData *CompressedImageData::clone() const
{
return new CompressedImageData(*this);
} }
CompressedImageData::~CompressedImageData() CompressedImageData::~CompressedImageData()
@@ -143,7 +139,7 @@ bool CompressedImageData::isSRGB() const
return sRGB; return sRGB;
} }
CompressedImageData::Slice *CompressedImageData::getSlice(int slice, int miplevel) const CompressedSlice *CompressedImageData::getSlice(int slice, int miplevel) const
{ {
checkSliceExists(slice, miplevel); checkSliceExists(slice, miplevel);
+12 -47
View File
@@ -25,10 +25,13 @@
#include "common/StringMap.h" #include "common/StringMap.h"
#include "common/int.h" #include "common/int.h"
#include "common/pixelformat.h" #include "common/pixelformat.h"
#include "ImageDataBase.h" #include "filesystem/FileData.h"
#include "CompressedSlice.h"
#include "CompressedFormatHandler.h"
// STL // STL
#include <vector> #include <vector>
#include <list>
namespace love namespace love
{ {
@@ -44,53 +47,16 @@ class CompressedImageData : public Data
{ {
public: public:
class Memory : public Object
{
public:
Memory(size_t size);
virtual ~Memory();
uint8 *data;
size_t size;
}; // Memory
// Compressed image data can have multiple mipmap levels, each represented
// by a sub-image.
class Slice : public ImageDataBase
{
public:
Slice(PixelFormat format, int width, int height, Memory *memory, size_t offset, size_t size);
Slice(const Slice &slice);
virtual ~Slice();
Slice *clone() const override;
void *getData() const override { return memory->data + offset; }
size_t getSize() const override { return dataSize; }
bool isSRGB() const override { return sRGB; }
size_t getOffset() const { return offset; }
private:
StrongRef<Memory> memory;
size_t offset;
size_t dataSize;
bool sRGB;
}; // Slice
static love::Type type; static love::Type type;
CompressedImageData(); CompressedImageData(const std::list<CompressedFormatHandler *> &formats, love::filesystem::FileData *filedata);
CompressedImageData(const CompressedImageData &c);
virtual ~CompressedImageData(); virtual ~CompressedImageData();
// Implements Data. // Implements Data.
virtual CompressedImageData *clone() const = 0; CompressedImageData *clone() const override;
virtual void *getData() const; void *getData() const override;
virtual size_t getSize() const; size_t getSize() const override;
/** /**
* Gets the number of mipmaps in this Compressed Image Data. * Gets the number of mipmaps in this Compressed Image Data.
@@ -130,19 +96,18 @@ public:
bool isSRGB() const; bool isSRGB() const;
Slice *getSlice(int slice, int miplevel) const; CompressedSlice *getSlice(int slice, int miplevel) const;
protected: protected:
PixelFormat format; PixelFormat format;
bool sRGB; bool sRGB;
// Single block of memory containing all of the sub-images. // Single block of memory containing all of the sub-images.
StrongRef<Memory> memory; StrongRef<CompressedMemory> memory;
// Texture info for each mipmap level. // Texture info for each mipmap level.
std::vector<StrongRef<Slice>> dataImages; std::vector<StrongRef<CompressedSlice>> dataImages;
void checkSliceExists(int slice, int miplevel) const; void checkSliceExists(int slice, int miplevel) const;
@@ -18,37 +18,61 @@
* 3. This notice may not be removed or altered from any source distribution. * 3. This notice may not be removed or altered from any source distribution.
**/ **/
#ifndef LOVE_IMAGE_MAGPIE_COMPRESSED_IMAGE_DATA_H #include "CompressedSlice.h"
#define LOVE_IMAGE_MAGPIE_COMPRESSED_IMAGE_DATA_H #include "common/Exception.h"
// LOVE
#include "CompressedFormatHandler.h"
#include "filesystem/FileData.h"
#include "image/CompressedImageData.h"
// C++
#include <list>
namespace love namespace love
{ {
namespace image namespace image
{ {
namespace magpie
CompressedMemory::CompressedMemory(size_t size)
: data(nullptr)
, size(size)
{ {
try
{
data = new uint8[size];
}
catch (std::exception &)
{
throw love::Exception("Out of memory.");
}
}
class CompressedImageData : public love::image::CompressedImageData CompressedMemory::~CompressedMemory()
{ {
public: delete[] data;
}
CompressedImageData(std::list<CompressedFormatHandler *> formats, love::filesystem::FileData *filedata); CompressedSlice::CompressedSlice(PixelFormat format, int width, int height, CompressedMemory *memory, size_t offset, size_t size)
CompressedImageData(const CompressedImageData &c); : memory(memory)
virtual ~CompressedImageData(); , offset(offset)
, dataSize(size)
{
this->format = format;
this->width = width;
this->height = height;
}
virtual CompressedImageData *clone() const; CompressedSlice::CompressedSlice(const CompressedSlice &s)
}; // CompressedImageData : memory(s.memory)
, offset(s.offset)
, dataSize(s.dataSize)
{
this->format = s.getFormat();
this->width = s.getWidth();
this->height = s.getHeight();
}
CompressedSlice::~CompressedSlice()
{
}
CompressedSlice *CompressedSlice::clone() const
{
return new CompressedSlice(*this);
}
} // magpie
} // image } // image
} // love } // love
#endif // LOVE_IMAGE_MAGPIE_COMPRESSED_IMAGE_DATA_H
+72
View File
@@ -0,0 +1,72 @@
/**
* Copyright (c) 2006-2017 LOVE Development Team
*
* 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.
**/
#pragma once
// LOVE
#include "common/int.h"
#include "common/pixelformat.h"
#include "common/Object.h"
#include "ImageDataBase.h"
namespace love
{
namespace image
{
class CompressedMemory : public Object
{
public:
CompressedMemory(size_t size);
virtual ~CompressedMemory();
uint8 *data;
size_t size;
}; // CompressedMemory
// Compressed image data can have multiple mipmap levels, each represented by a
// sub-image.
class CompressedSlice : public ImageDataBase
{
public:
CompressedSlice(PixelFormat format, int width, int height, CompressedMemory *memory, size_t offset, size_t size);
CompressedSlice(const CompressedSlice &slice);
virtual ~CompressedSlice();
CompressedSlice *clone() const override;
void *getData() const override { return memory->data + offset; }
size_t getSize() const override { return dataSize; }
bool isSRGB() const override { return sRGB; }
size_t getOffset() const { return offset; }
private:
StrongRef<CompressedMemory> memory;
size_t offset;
size_t dataSize;
bool sRGB;
}; // CompressedSlice
} // image
} // love
@@ -26,8 +26,6 @@ namespace love
{ {
namespace image namespace image
{ {
namespace magpie
{
FormatHandler::FormatHandler() FormatHandler::FormatHandler()
{ {
@@ -42,7 +40,7 @@ bool FormatHandler::canDecode(love::filesystem::FileData* /*data*/)
return false; return false;
} }
bool FormatHandler::canEncode(PixelFormat /*rawFormat*/, ImageData::EncodedFormat /*encodedFormat*/) bool FormatHandler::canEncode(PixelFormat /*rawFormat*/, EncodedFormat /*encodedFormat*/)
{ {
return false; return false;
} }
@@ -52,7 +50,7 @@ FormatHandler::DecodedImage FormatHandler::decode(love::filesystem::FileData* /*
throw love::Exception("Image decoding is not implemented for this format backend."); throw love::Exception("Image decoding is not implemented for this format backend.");
} }
FormatHandler::EncodedImage FormatHandler::encode(const DecodedImage& /*img*/, ImageData::EncodedFormat /*format*/) FormatHandler::EncodedImage FormatHandler::encode(const DecodedImage& /*img*/, EncodedFormat /*format*/)
{ {
throw love::Exception("Image encoding is not implemented for this format backend."); throw love::Exception("Image encoding is not implemented for this format backend.");
} }
@@ -62,6 +60,5 @@ void FormatHandler::free(unsigned char *mem)
delete[] mem; delete[] mem;
} }
} // magpie
} // image } // image
} // love } // love
@@ -18,20 +18,17 @@
* 3. This notice may not be removed or altered from any source distribution. * 3. This notice may not be removed or altered from any source distribution.
**/ **/
#ifndef LOVE_IMAGE_MAGPIE_FORMAT_HANDLER_H #pragma once
#define LOVE_IMAGE_MAGPIE_FORMAT_HANDLER_H
// LOVE // LOVE
#include "image/ImageData.h"
#include "filesystem/FileData.h"
#include "common/Object.h" #include "common/Object.h"
#include "common/pixelformat.h"
#include "filesystem/FileData.h"
namespace love namespace love
{ {
namespace image namespace image
{ {
namespace magpie
{
/** /**
* Base class for all ImageData encoder/decoder library interfaces. * Base class for all ImageData encoder/decoder library interfaces.
@@ -41,6 +38,13 @@ class FormatHandler : public love::Object
{ {
public: public:
enum EncodedFormat
{
ENCODED_TGA,
ENCODED_PNG,
ENCODED_MAX_ENUM
};
// Raw RGBA pixel data. // Raw RGBA pixel data.
struct DecodedImage struct DecodedImage
{ {
@@ -76,7 +80,7 @@ public:
/** /**
* Whether this format handler can encode to a particular format. * Whether this format handler can encode to a particular format.
**/ **/
virtual bool canEncode(PixelFormat rawFormat, ImageData::EncodedFormat encodedFormat); virtual bool canEncode(PixelFormat rawFormat, EncodedFormat encodedFormat);
/** /**
* Decodes an image from its encoded form into raw pixel data. * Decodes an image from its encoded form into raw pixel data.
@@ -91,7 +95,7 @@ public:
* @param format The format to encode to. * @param format The format to encode to.
* @return The encoded image data. * @return The encoded image data.
**/ **/
virtual EncodedImage encode(const DecodedImage &img, ImageData::EncodedFormat format); virtual EncodedImage encode(const DecodedImage &img, EncodedFormat format);
/** /**
* Frees memory allocated by the format handler. * Frees memory allocated by the format handler.
@@ -100,8 +104,5 @@ public:
}; // FormatHandler }; // FormatHandler
} // magpie
} // image } // image
} // love } // love
#endif // LOVE_IMAGE_MAGPIE_FORMAT_HANDLER_H
+84
View File
@@ -20,6 +20,17 @@
// LOVE // LOVE
#include "Image.h" #include "Image.h"
#include "common/config.h"
#include "magpie/PNGHandler.h"
#include "magpie/STBHandler.h"
#include "magpie/EXRHandler.h"
#include "magpie/ddsHandler.h"
#include "magpie/PVRHandler.h"
#include "magpie/KTXHandler.h"
#include "magpie/PKMHandler.h"
#include "magpie/ASTCHandler.h"
namespace love namespace love
{ {
@@ -28,6 +39,79 @@ namespace image
love::Type Image::type("image", &Module::type); love::Type Image::type("image", &Module::type);
Image::Image()
{
using namespace magpie;
halfInit(); // Makes sure half-float conversions can be used.
formatHandlers = {
new PNGHandler,
new STBHandler,
new EXRHandler,
};
compressedFormatHandlers = {
new DDSHandler,
new PVRHandler,
new KTXHandler,
new PKMHandler,
new ASTCHandler,
};
}
Image::~Image()
{
// ImageData objects reference the FormatHandlers in our list, so we should
// release them instead of deleting them completely here.
for (FormatHandler *handler : formatHandlers)
handler->release();
for (CompressedFormatHandler *handler : compressedFormatHandlers)
handler->release();
}
const char *Image::getName() const
{
return "love.image.magpie";
}
love::image::ImageData *Image::newImageData(love::filesystem::FileData *data)
{
return new ImageData(data);
}
love::image::ImageData *Image::newImageData(int width, int height, PixelFormat format)
{
return new ImageData(width, height, format);
}
love::image::ImageData *Image::newImageData(int width, int height, PixelFormat format, void *data, bool own)
{
return new ImageData(width, height, format, data, own);
}
love::image::CompressedImageData *Image::newCompressedData(love::filesystem::FileData *data)
{
return new CompressedImageData(compressedFormatHandlers, data);
}
bool Image::isCompressed(love::filesystem::FileData *data)
{
for (CompressedFormatHandler *handler : compressedFormatHandlers)
{
if (handler->canParse(data))
return true;
}
return false;
}
const std::list<FormatHandler *> &Image::getFormatHandlers() const
{
return formatHandlers;
}
ImageData *Image::newPastedImageData(ImageData *src, int sx, int sy, int w, int h) ImageData *Image::newPastedImageData(ImageData *src, int sx, int sy, int w, int h)
{ {
ImageData *res = newImageData(w, h, src->getFormat()); ImageData *res = newImageData(w, h, src->getFormat());
+20 -7
View File
@@ -28,6 +28,9 @@
#include "ImageData.h" #include "ImageData.h"
#include "CompressedImageData.h" #include "CompressedImageData.h"
// C++
#include <list>
namespace love namespace love
{ {
namespace image namespace image
@@ -46,17 +49,19 @@ public:
static love::Type type; static love::Type type;
virtual ~Image() {} Image();
virtual ~Image();
// Implements Module. // Implements Module.
virtual ModuleType getModuleType() const { return M_IMAGE; } ModuleType getModuleType() const override { return M_IMAGE; }
const char *getName() const override;
/** /**
* Creates new ImageData from FileData. * Creates new ImageData from FileData.
* @param data The FileData containing the encoded image data. * @param data The FileData containing the encoded image data.
* @return The new ImageData. * @return The new ImageData.
**/ **/
virtual ImageData *newImageData(love::filesystem::FileData *data) = 0; ImageData *newImageData(love::filesystem::FileData *data);
/** /**
* Creates empty ImageData with the given size. * Creates empty ImageData with the given size.
@@ -64,7 +69,7 @@ public:
* @param height The height of the ImageData. * @param height The height of the ImageData.
* @return The new ImageData. * @return The new ImageData.
**/ **/
virtual ImageData *newImageData(int width, int height, PixelFormat format = PIXELFORMAT_RGBA8) = 0; ImageData *newImageData(int width, int height, PixelFormat format = PIXELFORMAT_RGBA8);
/** /**
* Creates empty ImageData with the given size. * Creates empty ImageData with the given size.
@@ -75,28 +80,36 @@ public:
* copy it. * copy it.
* @return The new ImageData. * @return The new ImageData.
**/ **/
virtual ImageData *newImageData(int width, int height, PixelFormat format, void *data, bool own = false) = 0; ImageData *newImageData(int width, int height, PixelFormat format, void *data, bool own = false);
/** /**
* Creates new CompressedImageData from FileData. * Creates new CompressedImageData from FileData.
* @param data The FileData containing the compressed image data. * @param data The FileData containing the compressed image data.
* @return The new CompressedImageData. * @return The new CompressedImageData.
**/ **/
virtual CompressedImageData *newCompressedData(love::filesystem::FileData *data) = 0; CompressedImageData *newCompressedData(love::filesystem::FileData *data);
/** /**
* Determines whether a FileData is Compressed image data or not. * Determines whether a FileData is Compressed image data or not.
* @param data The FileData to test. * @param data The FileData to test.
**/ **/
virtual bool isCompressed(love::filesystem::FileData *data) = 0; bool isCompressed(love::filesystem::FileData *data);
std::vector<StrongRef<ImageData>> newCubeFaces(ImageData *src); std::vector<StrongRef<ImageData>> newCubeFaces(ImageData *src);
std::vector<StrongRef<ImageData>> newVolumeLayers(ImageData *src); std::vector<StrongRef<ImageData>> newVolumeLayers(ImageData *src);
const std::list<FormatHandler *> &getFormatHandlers() const;
private: private:
ImageData *newPastedImageData(ImageData *src, int sx, int sy, int w, int h); ImageData *newPastedImageData(ImageData *src, int sx, int sy, int w, int h);
// Image format handlers we can use for decoding and encoding ImageData.
std::list<FormatHandler *> formatHandlers;
// Compressed image format handers we can use for parsing CompressedImageData.
std::list<CompressedFormatHandler *> compressedFormatHandlers;
}; // Image }; // Image
} // image } // image
+204 -8
View File
@@ -19,6 +19,8 @@
**/ **/
#include "ImageData.h" #include "ImageData.h"
#include "Image.h"
#include "filesystem/Filesystem.h"
using love::thread::Lock; using love::thread::Lock;
@@ -29,13 +31,207 @@ namespace image
love::Type ImageData::type("ImageData", &Data::type); love::Type ImageData::type("ImageData", &Data::type);
ImageData::ImageData() ImageData::ImageData(love::filesystem::FileData *data)
: data(nullptr)
{ {
decode(data);
}
ImageData::ImageData(int width, int height, PixelFormat format)
{
if (!validPixelFormat(format))
throw love::Exception("Unsupported pixel format for ImageData");
this->width = width;
this->height = height;
this->format = format;
create(width, height, format);
// Set to black/transparency.
memset(data, 0, getSize());
}
ImageData::ImageData(int width, int height, PixelFormat format, void *data, bool own)
{
if (!validPixelFormat(format))
throw love::Exception("Unsupported pixel format for ImageData");
this->width = width;
this->height = height;
this->format = format;
if (own)
this->data = (unsigned char *) data;
else
create(width, height, format, data);
}
ImageData::ImageData(const ImageData &c)
{
width = c.width;
height = c.height;
format = c.format;
create(width, height, format, c.getData());
} }
ImageData::~ImageData() ImageData::~ImageData()
{ {
if (decodeHandler.get())
decodeHandler->free(data);
else
delete[] data;
}
love::image::ImageData *ImageData::clone() const
{
return new ImageData(*this);
}
void ImageData::create(int width, int height, PixelFormat format, void *data)
{
size_t datasize = width * height * getPixelFormatSize(format);
try
{
this->data = new unsigned char[datasize];
}
catch(std::bad_alloc &)
{
throw love::Exception("Out of memory");
}
if (data)
memcpy(this->data, data, datasize);
decodeHandler = nullptr;
this->format = format;
}
void ImageData::decode(love::filesystem::FileData *data)
{
FormatHandler *decoder = nullptr;
FormatHandler::DecodedImage decodedimage;
auto module = Module::getInstance<Image>(Module::M_IMAGE);
if (module == nullptr)
throw love::Exception("love.image must be loaded in order to decode an ImageData.");
for (FormatHandler *handler : module->getFormatHandlers())
{
if (handler->canDecode(data))
{
decoder = handler;
break;
}
}
if (decoder)
decodedimage = decoder->decode(data);
if (decodedimage.data == nullptr)
{
const std::string &name = data->getFilename();
throw love::Exception("Could not decode file '%s' to ImageData: unsupported file format", name.c_str());
}
if (decodedimage.size != decodedimage.width * decodedimage.height * getPixelFormatSize(decodedimage.format))
{
decoder->free(decodedimage.data);
throw love::Exception("Could not convert image!");
}
// Clean up any old data.
if (decodeHandler)
decodeHandler->free(this->data);
else
delete[] this->data;
this->width = decodedimage.width;
this->height = decodedimage.height;
this->data = decodedimage.data;
this->format = decodedimage.format;
decodeHandler = decoder;
}
love::filesystem::FileData *ImageData::encode(FormatHandler::EncodedFormat encodedFormat, const char *filename, bool writefile) const
{
FormatHandler *encoder = nullptr;
FormatHandler::EncodedImage encodedimage;
FormatHandler::DecodedImage rawimage;
rawimage.width = width;
rawimage.height = height;
rawimage.size = getSize();
rawimage.data = data;
rawimage.format = format;
auto module = Module::getInstance<Image>(Module::M_IMAGE);
if (module == nullptr)
throw love::Exception("love.image must be loaded in order to encode an ImageData.");
for (FormatHandler *handler : module->getFormatHandlers())
{
if (handler->canEncode(format, encodedFormat))
{
encoder = handler;
break;
}
}
if (encoder != nullptr)
{
thread::Lock lock(mutex);
encodedimage = encoder->encode(rawimage, encodedFormat);
}
if (encoder == nullptr || encodedimage.data == nullptr)
{
const char *fname = "unknown";
love::getConstant(format, fname);
throw love::Exception("No suitable image encoder for %s format.", fname);
}
love::filesystem::FileData *filedata = nullptr;
try
{
filedata = new love::filesystem::FileData(encodedimage.size, filename);
}
catch (love::Exception &)
{
encoder->free(encodedimage.data);
throw;
}
memcpy(filedata->getData(), encodedimage.data, encodedimage.size);
encoder->free(encodedimage.data);
if (writefile)
{
auto fs = Module::getInstance<filesystem::Filesystem>(Module::M_FILESYSTEM);
if (fs == nullptr)
{
filedata->release();
throw love::Exception("love.filesystem must be loaded in order to write an encoded ImageData to a file.");
}
try
{
fs->write(filename, filedata->getData(), filedata->getSize());
}
catch (love::Exception &)
{
filedata->release();
throw;
}
}
return filedata;
} }
size_t ImageData::getSize() const size_t ImageData::getSize() const
@@ -289,23 +485,23 @@ bool ImageData::validPixelFormat(PixelFormat format)
} }
} }
bool ImageData::getConstant(const char *in, EncodedFormat &out) bool ImageData::getConstant(const char *in, FormatHandler::EncodedFormat &out)
{ {
return encodedFormats.find(in, out); return encodedFormats.find(in, out);
} }
bool ImageData::getConstant(EncodedFormat in, const char *&out) bool ImageData::getConstant(FormatHandler::EncodedFormat in, const char *&out)
{ {
return encodedFormats.find(in, out); return encodedFormats.find(in, out);
} }
StringMap<ImageData::EncodedFormat, ImageData::ENCODED_MAX_ENUM>::Entry ImageData::encodedFormatEntries[] = StringMap<FormatHandler::EncodedFormat, FormatHandler::ENCODED_MAX_ENUM>::Entry ImageData::encodedFormatEntries[] =
{ {
{"tga", ENCODED_TGA}, {"tga", FormatHandler::ENCODED_TGA},
{"png", ENCODED_PNG}, {"png", FormatHandler::ENCODED_PNG},
}; };
StringMap<ImageData::EncodedFormat, ImageData::ENCODED_MAX_ENUM> ImageData::encodedFormats(ImageData::encodedFormatEntries, sizeof(ImageData::encodedFormatEntries)); StringMap<FormatHandler::EncodedFormat, FormatHandler::ENCODED_MAX_ENUM> ImageData::encodedFormats(ImageData::encodedFormatEntries, sizeof(ImageData::encodedFormatEntries));
} // image } // image
} // love } // love
+26 -31
View File
@@ -29,6 +29,7 @@
#include "filesystem/FileData.h" #include "filesystem/FileData.h"
#include "thread/threads.h" #include "thread/threads.h"
#include "ImageDataBase.h" #include "ImageDataBase.h"
#include "FormatHandler.h"
using love::thread::Mutex; using love::thread::Mutex;
@@ -37,13 +38,6 @@ namespace love
namespace image namespace image
{ {
// Pixel format structure.
struct pixel
{
// Red, green, blue, alpha.
unsigned char r, g, b, a;
};
union Pixel union Pixel
{ {
uint8 rgba8[4]; uint8 rgba8[4];
@@ -61,14 +55,10 @@ public:
static love::Type type; static love::Type type;
enum EncodedFormat ImageData(love::filesystem::FileData *data);
{ ImageData(int width, int height, PixelFormat format = PIXELFORMAT_RGBA8);
ENCODED_TGA, ImageData(int width, int height, PixelFormat format, void *data, bool own);
ENCODED_PNG, ImageData(const ImageData &c);
ENCODED_MAX_ENUM
};
ImageData();
virtual ~ImageData(); virtual ~ImageData();
/** /**
@@ -111,12 +101,12 @@ public:
* @param f The file to save the encoded image data to. * @param f The file to save the encoded image data to.
* @param format The format of the encoded data. * @param format The format of the encoded data.
**/ **/
virtual love::filesystem::FileData *encode(EncodedFormat format, const char *filename) = 0; love::filesystem::FileData *encode(FormatHandler::EncodedFormat format, const char *filename, bool writefile) const;
love::thread::Mutex *getMutex() const; love::thread::Mutex *getMutex() const;
// Implements ImageDataBase. // Implements ImageDataBase.
virtual ImageData *clone() const override = 0; ImageData *clone() const override;
void *getData() const override; void *getData() const override;
size_t getSize() const override; size_t getSize() const override;
bool isSRGB() const override; bool isSRGB() const override;
@@ -125,18 +115,8 @@ public:
static bool validPixelFormat(PixelFormat format); static bool validPixelFormat(PixelFormat format);
static bool getConstant(const char *in, EncodedFormat &out); static bool getConstant(const char *in, FormatHandler::EncodedFormat &out);
static bool getConstant(EncodedFormat in, const char *&out); static bool getConstant(FormatHandler::EncodedFormat in, const char *&out);
protected:
// The actual data.
unsigned char *data;
// We need to be thread-safe
// so we lock when we're accessing our
// data
love::thread::MutexRef mutex;
private: private:
@@ -148,6 +128,21 @@ private:
float *f32; float *f32;
}; };
// Create imagedata. Initialize with data if not null.
void create(int width, int height, PixelFormat format, void *data = nullptr);
// Decode and load an encoded format.
void decode(love::filesystem::FileData *data);
// The actual data.
unsigned char *data = nullptr;
love::thread::MutexRef mutex;
// The format handler that was used to decode the ImageData. We need to know
// this so we can properly delete memory allocated by the decoder.
StrongRef<FormatHandler> decodeHandler;
static void pasteRGBA8toRGBA16(Row src, Row dst, int w); static void pasteRGBA8toRGBA16(Row src, Row dst, int w);
static void pasteRGBA8toRGBA16F(Row src, Row dst, int w); static void pasteRGBA8toRGBA16F(Row src, Row dst, int w);
static void pasteRGBA8toRGBA32F(Row src, Row dst, int w); static void pasteRGBA8toRGBA32F(Row src, Row dst, int w);
@@ -164,8 +159,8 @@ private:
static void pasteRGBA32FtoRGBA16(Row src, Row dst, int w); static void pasteRGBA32FtoRGBA16(Row src, Row dst, int w);
static void pasteRGBA32FtoRGBA16F(Row src, Row dst, int w); static void pasteRGBA32FtoRGBA16F(Row src, Row dst, int w);
static StringMap<EncodedFormat, ENCODED_MAX_ENUM>::Entry encodedFormatEntries[]; static StringMap<FormatHandler::EncodedFormat, FormatHandler::ENCODED_MAX_ENUM>::Entry encodedFormatEntries[];
static StringMap<EncodedFormat, ENCODED_MAX_ENUM> encodedFormats; static StringMap<FormatHandler::EncodedFormat, FormatHandler::ENCODED_MAX_ENUM> encodedFormats;
}; // ImageData }; // ImageData
+3 -3
View File
@@ -104,7 +104,7 @@ bool ASTCHandler::canParse(const filesystem::FileData *data)
return true; return true;
} }
StrongRef<CompressedImageData::Memory> ASTCHandler::parse(filesystem::FileData *filedata, std::vector<StrongRef<CompressedImageData::Slice>> &images, PixelFormat &format, bool &sRGB) StrongRef<CompressedMemory> ASTCHandler::parse(filesystem::FileData *filedata, std::vector<StrongRef<CompressedSlice>> &images, PixelFormat &format, bool &sRGB)
{ {
if (!canParse(filedata)) if (!canParse(filedata))
throw love::Exception("Could not decode compressed data (not an .astc file?)"); throw love::Exception("Could not decode compressed data (not an .astc file?)");
@@ -129,12 +129,12 @@ StrongRef<CompressedImageData::Memory> ASTCHandler::parse(filesystem::FileData *
if (totalsize + sizeof(header) > filedata->getSize()) if (totalsize + sizeof(header) > filedata->getSize())
throw love::Exception("Could not parse .astc file: file is too small."); throw love::Exception("Could not parse .astc file: file is too small.");
StrongRef<CompressedImageData::Memory> memory(new CompressedImageData::Memory(totalsize), Acquire::NORETAIN); StrongRef<CompressedMemory> memory(new CompressedMemory(totalsize), Acquire::NORETAIN);
// .astc files only store a single mipmap level. // .astc files only store a single mipmap level.
memcpy(memory->data, (uint8 *) filedata->getData() + sizeof(ASTCHeader), totalsize); memcpy(memory->data, (uint8 *) filedata->getData() + sizeof(ASTCHeader), totalsize);
images.emplace_back(new CompressedImageData::Slice(cformat, sizeX, sizeY, memory, 0, totalsize), Acquire::NORETAIN); images.emplace_back(new CompressedSlice(cformat, sizeX, sizeY, memory, 0, totalsize), Acquire::NORETAIN);
format = cformat; format = cformat;
sRGB = false; sRGB = false;
+4 -7
View File
@@ -18,11 +18,10 @@
* 3. This notice may not be removed or altered from any source distribution. * 3. This notice may not be removed or altered from any source distribution.
**/ **/
#ifndef LOVE_IMAGE_MAGPIE_ASTC_HANDLER_H #pragma once
#define LOVE_IMAGE_MAGPIE_ASTC_HANDLER_H
#include "common/config.h" #include "common/config.h"
#include "CompressedFormatHandler.h" #include "image/CompressedFormatHandler.h"
namespace love namespace love
{ {
@@ -44,8 +43,8 @@ public:
// Implements CompressedFormatHandler. // Implements CompressedFormatHandler.
bool canParse(const filesystem::FileData *data) override; bool canParse(const filesystem::FileData *data) override;
StrongRef<CompressedImageData::Memory> parse(filesystem::FileData *filedata, StrongRef<CompressedMemory> parse(filesystem::FileData *filedata,
std::vector<StrongRef<CompressedImageData::Slice>> &images, std::vector<StrongRef<CompressedSlice>> &images,
PixelFormat &format, bool &sRGB) override; PixelFormat &format, bool &sRGB) override;
}; // ASTCHandler }; // ASTCHandler
@@ -53,5 +52,3 @@ public:
} // magpie } // magpie
} // image } // image
} // love } // love
#endif // LOVE_IMAGE_MAGPIE_ASTC_HANDLER_H
@@ -1,85 +0,0 @@
/**
* Copyright (c) 2006-2017 LOVE Development Team
*
* 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.
**/
#include "CompressedImageData.h"
namespace love
{
namespace image
{
namespace magpie
{
CompressedImageData::CompressedImageData(std::list<CompressedFormatHandler *> formats, love::filesystem::FileData *filedata)
{
CompressedFormatHandler *parser = nullptr;
for (CompressedFormatHandler *handler : formats)
{
if (handler->canParse(filedata))
{
parser = handler;
break;
}
}
if (parser == nullptr)
throw love::Exception("Could not parse compressed data: Unknown format.");
memory = parser->parse(filedata, dataImages, format, sRGB);
if (memory == nullptr)
throw love::Exception("Could not parse compressed data.");
if (format == PIXELFORMAT_UNKNOWN)
throw love::Exception("Could not parse compressed data: Unknown format.");
if (dataImages.size() == 0 || memory->size == 0)
throw love::Exception("Could not parse compressed data: No valid data?");
}
CompressedImageData::CompressedImageData(const CompressedImageData &c)
{
format = c.format;
sRGB = c.sRGB;
memory.set(new Memory(c.memory->size), Acquire::NORETAIN);
memcpy(memory->data, c.memory->data, memory->size);
for (const auto &i : c.dataImages)
{
Slice *slice = new Slice(i->getFormat(), i->getWidth(), i->getHeight(), memory, i->getOffset(), i->getSize());
dataImages.push_back(slice);
slice->release();
}
}
CompressedImageData *CompressedImageData::clone() const
{
return new CompressedImageData(*this);
}
CompressedImageData::~CompressedImageData()
{
}
} // magpie
} // image
} // love
+3 -2
View File
@@ -20,6 +20,7 @@
// LOVE // LOVE
#include "EXRHandler.h" #include "EXRHandler.h"
#include "common/halffloat.h"
// tinyexr // tinyexr
#define TINYEXR_IMPLEMENTATION #define TINYEXR_IMPLEMENTATION
@@ -41,7 +42,7 @@ bool EXRHandler::canDecode(love::filesystem::FileData *data)
return ParseEXRVersionFromMemory(&version, (const unsigned char *) data->getData(), data->getSize()) == TINYEXR_SUCCESS; return ParseEXRVersionFromMemory(&version, (const unsigned char *) data->getData(), data->getSize()) == TINYEXR_SUCCESS;
} }
bool EXRHandler::canEncode(PixelFormat /*rawFormat*/, ImageData::EncodedFormat /*encodedFormat*/) bool EXRHandler::canEncode(PixelFormat /*rawFormat*/, EncodedFormat /*encodedFormat*/)
{ {
return false; return false;
} }
@@ -186,7 +187,7 @@ FormatHandler::DecodedImage EXRHandler::decode(love::filesystem::FileData *data)
return img; return img;
} }
FormatHandler::EncodedImage EXRHandler::encode(const DecodedImage & /*img*/, ImageData::EncodedFormat /*encodedFormat*/) FormatHandler::EncodedImage EXRHandler::encode(const DecodedImage & /*img*/, EncodedFormat /*encodedFormat*/)
{ {
throw love::Exception("Invalid format."); throw love::Exception("Invalid format.");
} }

Some files were not shown because too many files have changed in this diff Show More