mirror of
https://github.com/love2d/love.git
synced 2026-08-12 08:30:56 +02:00
Merge branch '12.0-development' into 12.0-testsuite
This commit is contained in:
@@ -837,8 +837,6 @@ set(LOVE_SRC_MODULE_PHYSICS_BOX2D
|
||||
src/modules/physics/box2d/DistanceJoint.h
|
||||
src/modules/physics/box2d/EdgeShape.cpp
|
||||
src/modules/physics/box2d/EdgeShape.h
|
||||
src/modules/physics/box2d/Fixture.cpp
|
||||
src/modules/physics/box2d/Fixture.h
|
||||
src/modules/physics/box2d/FrictionJoint.cpp
|
||||
src/modules/physics/box2d/FrictionJoint.h
|
||||
src/modules/physics/box2d/GearJoint.cpp
|
||||
@@ -881,8 +879,6 @@ set(LOVE_SRC_MODULE_PHYSICS_BOX2D
|
||||
src/modules/physics/box2d/wrap_DistanceJoint.h
|
||||
src/modules/physics/box2d/wrap_EdgeShape.cpp
|
||||
src/modules/physics/box2d/wrap_EdgeShape.h
|
||||
src/modules/physics/box2d/wrap_Fixture.cpp
|
||||
src/modules/physics/box2d/wrap_Fixture.h
|
||||
src/modules/physics/box2d/wrap_FrictionJoint.cpp
|
||||
src/modules/physics/box2d/wrap_FrictionJoint.h
|
||||
src/modules/physics/box2d/wrap_GearJoint.cpp
|
||||
|
||||
@@ -51,6 +51,9 @@
|
||||
217DFC111D9F6D490055D849 /* usocket.c in Sources */ = {isa = PBXBuildFile; fileRef = 217DFBD51D9F6D490055D849 /* usocket.c */; };
|
||||
217DFC121D9F6D490055D849 /* usocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 217DFBD61D9F6D490055D849 /* usocket.h */; };
|
||||
D923E7D3296B85B9002FF1B3 /* harfbuzz.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = D923E7D2296B85B9002FF1B3 /* harfbuzz.xcframework */; };
|
||||
D943E58E2A24D56000D80361 /* PhysfsIo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D943E58C2A24D56000D80361 /* PhysfsIo.cpp */; };
|
||||
D943E58F2A24D56000D80361 /* PhysfsIo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D943E58C2A24D56000D80361 /* PhysfsIo.cpp */; };
|
||||
D943E5902A24D56000D80361 /* PhysfsIo.h in Headers */ = {isa = PBXBuildFile; fileRef = D943E58D2A24D56000D80361 /* PhysfsIo.h */; };
|
||||
D9DAB9222961F0EE00C64820 /* HarfbuzzShaper.h in Headers */ = {isa = PBXBuildFile; fileRef = D9DAB9202961F0EE00C64820 /* HarfbuzzShaper.h */; };
|
||||
D9DAB9232961F0EE00C64820 /* HarfbuzzShaper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D9DAB9212961F0EE00C64820 /* HarfbuzzShaper.cpp */; };
|
||||
D9DAB9242961F0EE00C64820 /* HarfbuzzShaper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D9DAB9212961F0EE00C64820 /* HarfbuzzShaper.cpp */; };
|
||||
@@ -61,9 +64,6 @@
|
||||
D9DAB92D2961F10000C64820 /* TextShaper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D9DAB9282961F10000C64820 /* TextShaper.cpp */; };
|
||||
D9DAB92E2961F10000C64820 /* TextShaper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D9DAB9282961F10000C64820 /* TextShaper.cpp */; };
|
||||
D9DAB9322963CD7500C64820 /* harfbuzz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D9DAB9312963CD7500C64820 /* harfbuzz.framework */; };
|
||||
D943E58E2A24D56000D80361 /* PhysfsIo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D943E58C2A24D56000D80361 /* PhysfsIo.cpp */; };
|
||||
D943E58F2A24D56000D80361 /* PhysfsIo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D943E58C2A24D56000D80361 /* PhysfsIo.cpp */; };
|
||||
D943E5902A24D56000D80361 /* PhysfsIo.h in Headers */ = {isa = PBXBuildFile; fileRef = D943E58D2A24D56000D80361 /* PhysfsIo.h */; };
|
||||
FA0A3A5F23366CE9001C269E /* floattypes.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0A3A5D23366CE9001C269E /* floattypes.h */; };
|
||||
FA0A3A6023366CE9001C269E /* floattypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0A3A5E23366CE9001C269E /* floattypes.cpp */; };
|
||||
FA0A3A6123366CE9001C269E /* floattypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0A3A5E23366CE9001C269E /* floattypes.cpp */; };
|
||||
@@ -407,9 +407,6 @@
|
||||
FA0B7E091A95902C000E1D17 /* EdgeShape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C291A95902C000E1D17 /* EdgeShape.cpp */; };
|
||||
FA0B7E0A1A95902C000E1D17 /* EdgeShape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C291A95902C000E1D17 /* EdgeShape.cpp */; };
|
||||
FA0B7E0B1A95902C000E1D17 /* EdgeShape.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7C2A1A95902C000E1D17 /* EdgeShape.h */; };
|
||||
FA0B7E0C1A95902C000E1D17 /* Fixture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C2B1A95902C000E1D17 /* Fixture.cpp */; };
|
||||
FA0B7E0D1A95902C000E1D17 /* Fixture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C2B1A95902C000E1D17 /* Fixture.cpp */; };
|
||||
FA0B7E0E1A95902C000E1D17 /* Fixture.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7C2C1A95902C000E1D17 /* Fixture.h */; };
|
||||
FA0B7E0F1A95902C000E1D17 /* FrictionJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C2D1A95902C000E1D17 /* FrictionJoint.cpp */; };
|
||||
FA0B7E101A95902C000E1D17 /* FrictionJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C2D1A95902C000E1D17 /* FrictionJoint.cpp */; };
|
||||
FA0B7E111A95902C000E1D17 /* FrictionJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7C2E1A95902C000E1D17 /* FrictionJoint.h */; };
|
||||
@@ -473,9 +470,6 @@
|
||||
FA0B7E4B1A95902C000E1D17 /* wrap_EdgeShape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C551A95902C000E1D17 /* wrap_EdgeShape.cpp */; };
|
||||
FA0B7E4C1A95902C000E1D17 /* wrap_EdgeShape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C551A95902C000E1D17 /* wrap_EdgeShape.cpp */; };
|
||||
FA0B7E4D1A95902C000E1D17 /* wrap_EdgeShape.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7C561A95902C000E1D17 /* wrap_EdgeShape.h */; };
|
||||
FA0B7E4E1A95902C000E1D17 /* wrap_Fixture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C571A95902C000E1D17 /* wrap_Fixture.cpp */; };
|
||||
FA0B7E4F1A95902C000E1D17 /* wrap_Fixture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C571A95902C000E1D17 /* wrap_Fixture.cpp */; };
|
||||
FA0B7E501A95902C000E1D17 /* wrap_Fixture.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7C581A95902C000E1D17 /* wrap_Fixture.h */; };
|
||||
FA0B7E511A95902C000E1D17 /* wrap_FrictionJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C591A95902C000E1D17 /* wrap_FrictionJoint.cpp */; };
|
||||
FA0B7E521A95902C000E1D17 /* wrap_FrictionJoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7C591A95902C000E1D17 /* wrap_FrictionJoint.cpp */; };
|
||||
FA0B7E531A95902C000E1D17 /* wrap_FrictionJoint.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7C5A1A95902C000E1D17 /* wrap_FrictionJoint.h */; };
|
||||
@@ -1406,6 +1400,8 @@
|
||||
217DFBD51D9F6D490055D849 /* usocket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = usocket.c; sourceTree = "<group>"; };
|
||||
217DFBD61D9F6D490055D849 /* usocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = usocket.h; sourceTree = "<group>"; };
|
||||
D923E7D2296B85B9002FF1B3 /* harfbuzz.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = harfbuzz.xcframework; path = ios/libraries/harfbuzz.xcframework; sourceTree = "<group>"; };
|
||||
D943E58C2A24D56000D80361 /* PhysfsIo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PhysfsIo.cpp; sourceTree = "<group>"; };
|
||||
D943E58D2A24D56000D80361 /* PhysfsIo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PhysfsIo.h; sourceTree = "<group>"; };
|
||||
D9DAB9202961F0EE00C64820 /* HarfbuzzShaper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HarfbuzzShaper.h; sourceTree = "<group>"; };
|
||||
D9DAB9212961F0EE00C64820 /* HarfbuzzShaper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HarfbuzzShaper.cpp; sourceTree = "<group>"; };
|
||||
D9DAB9252961F0FF00C64820 /* GenericShaper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GenericShaper.h; sourceTree = "<group>"; };
|
||||
@@ -1413,8 +1409,6 @@
|
||||
D9DAB9272961F0FF00C64820 /* TextShaper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextShaper.h; sourceTree = "<group>"; };
|
||||
D9DAB9282961F10000C64820 /* TextShaper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextShaper.cpp; sourceTree = "<group>"; };
|
||||
D9DAB9312963CD7500C64820 /* harfbuzz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = harfbuzz.framework; path = macosx/Frameworks/harfbuzz.framework; sourceTree = "<group>"; };
|
||||
D943E58C2A24D56000D80361 /* PhysfsIo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PhysfsIo.cpp; sourceTree = "<group>"; };
|
||||
D943E58D2A24D56000D80361 /* PhysfsIo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PhysfsIo.h; sourceTree = "<group>"; };
|
||||
FA08F5AE16C7525600F007B5 /* liblove-macosx.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "liblove-macosx.plist"; path = "macosx/liblove-macosx.plist"; sourceTree = "<group>"; };
|
||||
FA0A3A5D23366CE9001C269E /* floattypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = floattypes.h; sourceTree = "<group>"; };
|
||||
FA0A3A5E23366CE9001C269E /* floattypes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = floattypes.cpp; sourceTree = "<group>"; };
|
||||
@@ -1652,8 +1646,6 @@
|
||||
FA0B7C281A95902C000E1D17 /* DistanceJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DistanceJoint.h; sourceTree = "<group>"; };
|
||||
FA0B7C291A95902C000E1D17 /* EdgeShape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EdgeShape.cpp; sourceTree = "<group>"; };
|
||||
FA0B7C2A1A95902C000E1D17 /* EdgeShape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EdgeShape.h; sourceTree = "<group>"; };
|
||||
FA0B7C2B1A95902C000E1D17 /* Fixture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Fixture.cpp; sourceTree = "<group>"; };
|
||||
FA0B7C2C1A95902C000E1D17 /* Fixture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Fixture.h; sourceTree = "<group>"; };
|
||||
FA0B7C2D1A95902C000E1D17 /* FrictionJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FrictionJoint.cpp; sourceTree = "<group>"; };
|
||||
FA0B7C2E1A95902C000E1D17 /* FrictionJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FrictionJoint.h; sourceTree = "<group>"; };
|
||||
FA0B7C2F1A95902C000E1D17 /* GearJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GearJoint.cpp; sourceTree = "<group>"; };
|
||||
@@ -1696,8 +1688,6 @@
|
||||
FA0B7C541A95902C000E1D17 /* wrap_DistanceJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_DistanceJoint.h; sourceTree = "<group>"; };
|
||||
FA0B7C551A95902C000E1D17 /* wrap_EdgeShape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_EdgeShape.cpp; sourceTree = "<group>"; };
|
||||
FA0B7C561A95902C000E1D17 /* wrap_EdgeShape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_EdgeShape.h; sourceTree = "<group>"; };
|
||||
FA0B7C571A95902C000E1D17 /* wrap_Fixture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Fixture.cpp; sourceTree = "<group>"; };
|
||||
FA0B7C581A95902C000E1D17 /* wrap_Fixture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Fixture.h; sourceTree = "<group>"; };
|
||||
FA0B7C591A95902C000E1D17 /* wrap_FrictionJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_FrictionJoint.cpp; sourceTree = "<group>"; };
|
||||
FA0B7C5A1A95902C000E1D17 /* wrap_FrictionJoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_FrictionJoint.h; sourceTree = "<group>"; };
|
||||
FA0B7C5B1A95902C000E1D17 /* wrap_GearJoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_GearJoint.cpp; sourceTree = "<group>"; };
|
||||
@@ -3165,8 +3155,6 @@
|
||||
FA0B7C281A95902C000E1D17 /* DistanceJoint.h */,
|
||||
FA0B7C291A95902C000E1D17 /* EdgeShape.cpp */,
|
||||
FA0B7C2A1A95902C000E1D17 /* EdgeShape.h */,
|
||||
FA0B7C2B1A95902C000E1D17 /* Fixture.cpp */,
|
||||
FA0B7C2C1A95902C000E1D17 /* Fixture.h */,
|
||||
FA0B7C2D1A95902C000E1D17 /* FrictionJoint.cpp */,
|
||||
FA0B7C2E1A95902C000E1D17 /* FrictionJoint.h */,
|
||||
FA0B7C2F1A95902C000E1D17 /* GearJoint.cpp */,
|
||||
@@ -3209,8 +3197,6 @@
|
||||
FA0B7C541A95902C000E1D17 /* wrap_DistanceJoint.h */,
|
||||
FA0B7C551A95902C000E1D17 /* wrap_EdgeShape.cpp */,
|
||||
FA0B7C561A95902C000E1D17 /* wrap_EdgeShape.h */,
|
||||
FA0B7C571A95902C000E1D17 /* wrap_Fixture.cpp */,
|
||||
FA0B7C581A95902C000E1D17 /* wrap_Fixture.h */,
|
||||
FA0B7C591A95902C000E1D17 /* wrap_FrictionJoint.cpp */,
|
||||
FA0B7C5A1A95902C000E1D17 /* wrap_FrictionJoint.h */,
|
||||
FA0B7C5B1A95902C000E1D17 /* wrap_GearJoint.cpp */,
|
||||
@@ -4272,7 +4258,6 @@
|
||||
FAFEB29B28F210550025D7D0 /* unixdgram.h in Headers */,
|
||||
FA0B7E051A95902C000E1D17 /* Contact.h in Headers */,
|
||||
FA4F2BE41DE6650600CA37D7 /* Transform.h in Headers */,
|
||||
FA0B7E0E1A95902C000E1D17 /* Fixture.h in Headers */,
|
||||
FA6A2B661F5F7B6B0074C308 /* wrap_Data.h in Headers */,
|
||||
FA18CEE423DBC6E000263725 /* Graphics.h in Headers */,
|
||||
217DFBE81D9F6D490055D849 /* inet.h in Headers */,
|
||||
@@ -4467,7 +4452,6 @@
|
||||
FA4F2B7A1DE0125B00CA37D7 /* xxhash.h in Headers */,
|
||||
FA0B7DDE1A95902C000E1D17 /* wrap_BezierCurve.h in Headers */,
|
||||
FA0B7DED1A95902C000E1D17 /* Cursor.h in Headers */,
|
||||
FA0B7E501A95902C000E1D17 /* wrap_Fixture.h in Headers */,
|
||||
FA28EBD71E352DB5003446F4 /* FenceSync.h in Headers */,
|
||||
FADF542C1E3DAADA00012CC0 /* wrap_Mesh.h in Headers */,
|
||||
FAA3A9B01B7D465A00CED060 /* android.h in Headers */,
|
||||
@@ -4707,7 +4691,6 @@
|
||||
FA3C5E431F8C368C0003C579 /* ShaderStage.cpp in Sources */,
|
||||
FA0B7E191A95902C000E1D17 /* MotorJoint.cpp in Sources */,
|
||||
FAF1406F1E20934C00F898D2 /* Initialize.cpp in Sources */,
|
||||
FA0B7E4F1A95902C000E1D17 /* wrap_Fixture.cpp in Sources */,
|
||||
FA0B7EBF1A95902C000E1D17 /* Thread.cpp in Sources */,
|
||||
FACA02F91F5E39790084B28F /* Compressor.cpp in Sources */,
|
||||
FABDAA002552448300B5C523 /* b2_time_of_impact.cpp in Sources */,
|
||||
@@ -4725,7 +4708,6 @@
|
||||
FA4F2C111DE936FE00CA37D7 /* unix.c in Sources */,
|
||||
FA1BA0A31E16D97500AA2803 /* wrap_Font.cpp in Sources */,
|
||||
FABDA9842552448200B5C523 /* b2_chain_polygon_contact.cpp in Sources */,
|
||||
FA0B7E0D1A95902C000E1D17 /* Fixture.cpp in Sources */,
|
||||
FADF53FE1E3D74F200012CC0 /* TextBatch.cpp in Sources */,
|
||||
FA0B7D191A95902C000E1D17 /* TrueTypeRasterizer.cpp in Sources */,
|
||||
FAC271E723B5B5B400C200D3 /* renderstate.cpp in Sources */,
|
||||
@@ -5140,7 +5122,6 @@
|
||||
FAF140971E20934C00F898D2 /* PpTokens.cpp in Sources */,
|
||||
FAF140A91E20934C00F898D2 /* SymbolTable.cpp in Sources */,
|
||||
FA0B7E181A95902C000E1D17 /* MotorJoint.cpp in Sources */,
|
||||
FA0B7E4E1A95902C000E1D17 /* wrap_Fixture.cpp in Sources */,
|
||||
FA18CEC523D3AE6700263725 /* wrap_Buffer.cpp in Sources */,
|
||||
FAF6C9F423C2DE2900D7B5BC /* Logger.cpp in Sources */,
|
||||
FABDA9FF2552448300B5C523 /* b2_time_of_impact.cpp in Sources */,
|
||||
@@ -5159,7 +5140,6 @@
|
||||
FABDA9832552448200B5C523 /* b2_chain_polygon_contact.cpp in Sources */,
|
||||
FA0B7AD61A958EA3000E1D17 /* win32.c in Sources */,
|
||||
FADF54341E3DAE6E00012CC0 /* wrap_SpriteBatch.cpp in Sources */,
|
||||
FA0B7E0C1A95902C000E1D17 /* Fixture.cpp in Sources */,
|
||||
FA0B7D181A95902C000E1D17 /* TrueTypeRasterizer.cpp in Sources */,
|
||||
FA84DE6627791C36002674C6 /* GraphicsReadback.cpp in Sources */,
|
||||
FA0B7CFA1A95902C000E1D17 /* Filesystem.cpp in Sources */,
|
||||
@@ -5531,7 +5511,7 @@
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LIBRARY_SEARCH_PATHS = "";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.9;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
SDKROOT = macosx;
|
||||
USE_HEADERMAP = NO;
|
||||
@@ -5597,7 +5577,7 @@
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LIBRARY_SEARCH_PATHS = "";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.9;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
USE_HEADERMAP = NO;
|
||||
@@ -5736,7 +5716,7 @@
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LIBRARY_SEARCH_PATHS = "";
|
||||
LLVM_LTO = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.9;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
SDKROOT = macosx;
|
||||
USE_HEADERMAP = NO;
|
||||
|
||||
@@ -564,7 +564,7 @@
|
||||
INFOPLIST_FILE = "love-Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.9;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PRODUCT_NAME = love;
|
||||
SDKROOT = macosx;
|
||||
@@ -640,7 +640,7 @@
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks";
|
||||
LLVM_LTO = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.9;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
PRODUCT_NAME = love;
|
||||
SCAN_ALL_SOURCE_FILES_FOR_INCLUDES = YES;
|
||||
@@ -874,7 +874,7 @@
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks";
|
||||
LLVM_LTO = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.9;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
PRODUCT_NAME = love;
|
||||
SCAN_ALL_SOURCE_FILES_FOR_INCLUDES = YES;
|
||||
|
||||
@@ -6,7 +6,7 @@ Documentation
|
||||
-------------
|
||||
|
||||
We use our [wiki][wiki] for documentation.
|
||||
If you need further help, feel free to ask on our [forums][forums], our [Discord server][discord], or our IRC channel [#love on OFTC][irc].
|
||||
If you need further help, feel free to ask on our [forums][forums], our [Discord server][discord], or our [subreddit][subreddit].
|
||||
|
||||
Repository
|
||||
----------
|
||||
@@ -97,7 +97,7 @@ Dependencies
|
||||
[wiki]: https://love2d.org/wiki
|
||||
[forums]: https://love2d.org/forums
|
||||
[discord]: https://discord.gg/rhUets9
|
||||
[irc]: irc://irc.oftc.net/love
|
||||
[subreddit]: https://www.reddit.com/r/love2d
|
||||
[dependencies-apple]: https://github.com/love2d/love-apple-dependencies
|
||||
[dependencies-ios]: https://github.com/love2d/love/releases
|
||||
[megasource]: https://github.com/love2d/megasource
|
||||
|
||||
@@ -46,7 +46,7 @@ struct Optional
|
||||
hasValue = true;
|
||||
}
|
||||
|
||||
T get(T defaultVal)
|
||||
T get(T defaultVal) const
|
||||
{
|
||||
return hasValue ? value : defaultVal;
|
||||
}
|
||||
|
||||
@@ -107,8 +107,12 @@ std::string getDeprecationNotice(const DeprecationInfo &info, bool usewhere)
|
||||
|
||||
if (info.apiType == API_FUNCTION)
|
||||
notice << "function ";
|
||||
else if (info.apiType == API_FUNCTION_VARIANT)
|
||||
notice << "function variant in ";
|
||||
else if (info.apiType == API_METHOD)
|
||||
notice << "method ";
|
||||
else if (info.apiType == API_METHOD_VARIANT)
|
||||
notice << "method variant in ";
|
||||
else if (info.apiType == API_CALLBACK)
|
||||
notice << "callback ";
|
||||
else if (info.apiType == API_FIELD)
|
||||
@@ -188,7 +192,9 @@ MarkDeprecated::~MarkDeprecated()
|
||||
STRINGMAP_BEGIN(APIType, API_MAX_ENUM, apiType)
|
||||
{
|
||||
{ "function", API_FUNCTION },
|
||||
{ "functionvariant", API_FUNCTION_VARIANT },
|
||||
{ "method", API_METHOD },
|
||||
{ "methodvariant", API_METHOD_VARIANT },
|
||||
{ "callback", API_CALLBACK },
|
||||
{ "field", API_FIELD },
|
||||
{ "constant", API_CONSTANT },
|
||||
|
||||
@@ -32,7 +32,9 @@ namespace love
|
||||
enum APIType
|
||||
{
|
||||
API_FUNCTION,
|
||||
API_FUNCTION_VARIANT,
|
||||
API_METHOD,
|
||||
API_METHOD_VARIANT,
|
||||
API_CALLBACK,
|
||||
API_FIELD,
|
||||
API_CONSTANT,
|
||||
|
||||
+242
-145
@@ -26,101 +26,126 @@ namespace love
|
||||
|
||||
static PixelFormatInfo formatInfo[] =
|
||||
{
|
||||
// components, blockW, blockH, blockSize, color, depth, stencil, compressed, dataType
|
||||
{ 0, 1, 1, 0, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_UNKNOWN
|
||||
// components, blockW, blockH, blockSize, color, depth, stencil, compressed, sRGB, dataType
|
||||
{ 0, 1, 1, 0, false, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_UNKNOWN
|
||||
|
||||
{ 0, 1, 1, 0, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_NORMAL
|
||||
{ 0, 1, 1, 0, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_HDR
|
||||
{ 0, 1, 1, 0, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_NORMAL
|
||||
{ 0, 1, 1, 0, true, false, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_HDR
|
||||
|
||||
{ 1, 1, 1, 1, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_R8_UNORM
|
||||
{ 1, 1, 1, 1, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_R8_INT
|
||||
{ 1, 1, 1, 1, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_R8_UINT
|
||||
{ 1, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_R16_UNORM
|
||||
{ 1, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_R16_FLOAT
|
||||
{ 1, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_R16_INT
|
||||
{ 1, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_R16_UINT
|
||||
{ 1, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_R32_FLOAT
|
||||
{ 1, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_R32_INT
|
||||
{ 1, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_R32_UINT
|
||||
{ 1, 1, 1, 1, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_R8_UNORM
|
||||
{ 1, 1, 1, 1, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_R8_INT
|
||||
{ 1, 1, 1, 1, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_R8_UINT
|
||||
{ 1, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_R16_UNORM
|
||||
{ 1, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_R16_FLOAT
|
||||
{ 1, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_R16_INT
|
||||
{ 1, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_R16_UINT
|
||||
{ 1, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_R32_FLOAT
|
||||
{ 1, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_R32_INT
|
||||
{ 1, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_R32_UINT
|
||||
|
||||
{ 2, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RG8_UNORM
|
||||
{ 2, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RG8_INT
|
||||
{ 2, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RG8_UINT
|
||||
{ 2, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_LA8_UNORM
|
||||
{ 2, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RG16_UNORM
|
||||
{ 2, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RG16_FLOAT
|
||||
{ 2, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RG16_INT
|
||||
{ 2, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RG16_UINT
|
||||
{ 2, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RG32_FLOAT
|
||||
{ 2, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RG32_INT
|
||||
{ 2, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RG32_UINT
|
||||
{ 2, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RG8_UNORM
|
||||
{ 2, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RG8_INT
|
||||
{ 2, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RG8_UINT
|
||||
{ 2, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_LA8_UNORM
|
||||
{ 2, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RG16_UNORM
|
||||
{ 2, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RG16_FLOAT
|
||||
{ 2, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RG16_INT
|
||||
{ 2, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RG16_UINT
|
||||
{ 2, 1, 1, 8, true, false, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RG32_FLOAT
|
||||
{ 2, 1, 1, 8, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RG32_INT
|
||||
{ 2, 1, 1, 8, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RG32_UINT
|
||||
|
||||
{ 4, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA8_UNORM
|
||||
{ 4, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA8_UNORM_sRGB
|
||||
{ 4, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BGRA8_UNORM
|
||||
{ 4, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BGRA8_UNORM_sRGB
|
||||
{ 4, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RGBA8_INT
|
||||
{ 4, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RGBA8_UINT
|
||||
{ 4, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA16_UNORM
|
||||
{ 4, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RGBA16_FLOAT
|
||||
{ 4, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RGBA16_INT
|
||||
{ 4, 1, 1, 8, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RGBA16_UINT
|
||||
{ 4, 1, 1, 16, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RGBA32_FLOAT
|
||||
{ 4, 1, 1, 16, true, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RGBA32_INT
|
||||
{ 4, 1, 1, 16, true, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RGBA32_UINT
|
||||
{ 4, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA8_UNORM
|
||||
{ 4, 1, 1, 4, true, false, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA8_sRGB
|
||||
{ 4, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BGRA8_UNORM
|
||||
{ 4, 1, 1, 4, true, false, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BGRA8_sRGB
|
||||
{ 4, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RGBA8_INT
|
||||
{ 4, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RGBA8_UINT
|
||||
{ 4, 1, 1, 8, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA16_UNORM
|
||||
{ 4, 1, 1, 8, true, false, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RGBA16_FLOAT
|
||||
{ 4, 1, 1, 8, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RGBA16_INT
|
||||
{ 4, 1, 1, 8, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RGBA16_UINT
|
||||
{ 4, 1, 1, 16, true, false, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_RGBA32_FLOAT
|
||||
{ 4, 1, 1, 16, true, false, false, false, false, PIXELFORMATTYPE_SINT }, // PIXELFORMAT_RGBA32_INT
|
||||
{ 4, 1, 1, 16, true, false, false, false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_RGBA32_UINT
|
||||
|
||||
{ 4, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA4_UNORM
|
||||
{ 4, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGB5A1_UNORM
|
||||
{ 3, 1, 1, 2, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGB565_UNORM
|
||||
{ 4, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGB10A2_UNORM
|
||||
{ 3, 1, 1, 4, true, false, false, false, PIXELFORMATTYPE_UFLOAT }, // PIXELFORMAT_RG11B10_FLOAT
|
||||
{ 4, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGBA4_UNORM
|
||||
{ 4, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGB5A1_UNORM
|
||||
{ 3, 1, 1, 2, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGB565_UNORM
|
||||
{ 4, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_RGB10A2_UNORM
|
||||
{ 3, 1, 1, 4, true, false, false, false, false, PIXELFORMATTYPE_UFLOAT }, // PIXELFORMAT_RG11B10_FLOAT
|
||||
|
||||
{ 1, 1, 1, 1, false, false, true , false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_STENCIL8
|
||||
{ 1, 1, 1, 2, false, true, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DEPTH16_UNORM
|
||||
{ 1, 1, 1, 3, false, true, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DEPTH24_UNORM
|
||||
{ 1, 1, 1, 4, false, true, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_DEPTH32_FLOAT
|
||||
{ 2, 1, 1, 4, false, true, true , false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DEPTH24_UNORM_STENCIL8
|
||||
{ 2, 1, 1, 5, false, true, true , false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_DEPTH32_FLOAT_STENCIL8
|
||||
{ 1, 1, 1, 1, false, false, true , false, false, PIXELFORMATTYPE_UINT }, // PIXELFORMAT_STENCIL8
|
||||
{ 1, 1, 1, 2, false, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DEPTH16_UNORM
|
||||
{ 1, 1, 1, 3, false, true, false, false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DEPTH24_UNORM
|
||||
{ 1, 1, 1, 4, false, true, false, false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_DEPTH32_FLOAT
|
||||
{ 2, 1, 1, 4, false, true, true , false, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DEPTH24_UNORM_STENCIL8
|
||||
{ 2, 1, 1, 5, false, true, true , false, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_DEPTH32_FLOAT_STENCIL8
|
||||
|
||||
{ 3, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT1_UNORM
|
||||
{ 4, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT3_UNORM
|
||||
{ 4, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT5_UNORM
|
||||
{ 1, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BC4_UNORM
|
||||
{ 1, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_BC4_SNORM
|
||||
{ 2, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BC5_UNORM
|
||||
{ 2, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_BC5_SNORM
|
||||
{ 3, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UFLOAT }, // PIXELFORMAT_BC6H_UFLOAT
|
||||
{ 3, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_BC6H_FLOAT
|
||||
{ 4, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BC7_UNORM
|
||||
{ 3, 4, 4, 8, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT1_UNORM
|
||||
{ 3, 4, 4, 8, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT1_sRGB
|
||||
{ 4, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT3_UNORM
|
||||
{ 4, 4, 4, 16, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT3_sRGB
|
||||
{ 4, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT5_UNORM
|
||||
{ 4, 4, 4, 16, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_DXT5_sRGB
|
||||
{ 1, 4, 4, 8, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BC4_UNORM
|
||||
{ 1, 4, 4, 8, true, false, false, true, false, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_BC4_SNORM
|
||||
{ 2, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BC5_UNORM
|
||||
{ 2, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_BC5_SNORM
|
||||
{ 3, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_UFLOAT }, // PIXELFORMAT_BC6H_UFLOAT
|
||||
{ 3, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_SFLOAT }, // PIXELFORMAT_BC6H_FLOAT
|
||||
{ 4, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BC7_UNORM
|
||||
{ 4, 4, 4, 16, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_BC7_sRGB
|
||||
|
||||
{ 3, 16, 8, 32, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGB2_UNORM
|
||||
{ 3, 8, 8, 32, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGB4_UNORM
|
||||
{ 4, 16, 8, 32, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGBA2_UNORM
|
||||
{ 4, 8, 8, 32, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGBA4_UNORM
|
||||
{ 3, 16, 8, 32, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGB2_UNORM
|
||||
{ 3, 16, 8, 32, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGB2_sRGB
|
||||
{ 3, 8, 8, 32, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGB4_UNORM
|
||||
{ 3, 8, 8, 32, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGB4_sRGB
|
||||
{ 4, 16, 8, 32, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGBA2_UNORM
|
||||
{ 4, 16, 8, 32, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGBA2_sRGB
|
||||
{ 4, 8, 8, 32, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGBA4_UNORM
|
||||
{ 4, 8, 8, 32, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_PVR1_RGBA4_sRGB
|
||||
|
||||
{ 3, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC1_UNORM
|
||||
{ 3, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGB_UNORM
|
||||
{ 4, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGBA_UNORM
|
||||
{ 4, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGBA1_UNORM
|
||||
{ 1, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_EAC_R_UNORM
|
||||
{ 1, 4, 4, 8, true, false, false, true, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_EAC_R_SNORM
|
||||
{ 2, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_EAC_RG_UNORM
|
||||
{ 2, 4, 4, 16, true, false, false, true, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_EAC_RG_SNORM
|
||||
{ 3, 4, 4, 8, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC1_UNORM
|
||||
{ 3, 4, 4, 8, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGB_UNORM
|
||||
{ 3, 4, 4, 8, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGB_sRGB
|
||||
{ 4, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGBA_UNORM
|
||||
{ 4, 4, 4, 16, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGBA_sRGB
|
||||
{ 4, 4, 4, 8, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGBA1_UNORM
|
||||
{ 4, 4, 4, 8, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ETC2_RGBA1_sRGB
|
||||
{ 1, 4, 4, 8, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_EAC_R_UNORM
|
||||
{ 1, 4, 4, 8, true, false, false, true, false, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_EAC_R_SNORM
|
||||
{ 2, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_EAC_RG_UNORM
|
||||
{ 2, 4, 4, 16, true, false, false, true, false, PIXELFORMATTYPE_SNORM }, // PIXELFORMAT_EAC_RG_SNORM
|
||||
|
||||
{ 4, 4, 4, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_4x4
|
||||
{ 4, 5, 4, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_5x4
|
||||
{ 4, 5, 5, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_5x5
|
||||
{ 4, 6, 5, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_6x5
|
||||
{ 4, 6, 6, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_6x6
|
||||
{ 4, 8, 5, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x5
|
||||
{ 4, 8, 6, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x6
|
||||
{ 4, 8, 8, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x8
|
||||
{ 4, 8, 5, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x5
|
||||
{ 4, 10, 6, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x6
|
||||
{ 4, 10, 8, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x8
|
||||
{ 4, 10, 10, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x10
|
||||
{ 4, 12, 10, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_12x10
|
||||
{ 4, 12, 12, 1, true, false, false, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_12x12
|
||||
{ 4, 4, 4, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_4x4_UNORM
|
||||
{ 4, 5, 4, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_5x4_UNORM
|
||||
{ 4, 5, 5, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_5x5_UNORM
|
||||
{ 4, 6, 5, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_6x5_UNORM
|
||||
{ 4, 6, 6, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_6x6_UNORM
|
||||
{ 4, 8, 5, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x5_UNORM
|
||||
{ 4, 8, 6, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x6_UNORM
|
||||
{ 4, 8, 8, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x8_UNORM
|
||||
{ 4, 8, 5, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x5_UNORM
|
||||
{ 4, 10, 6, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x6_UNORM
|
||||
{ 4, 10, 8, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x8_UNORM
|
||||
{ 4, 10, 10, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x10_UNORM
|
||||
{ 4, 12, 10, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_12x10_UNORM
|
||||
{ 4, 12, 12, 1, true, false, false, true, false, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_12x12_UNORM
|
||||
{ 4, 4, 4, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_4x4_sRGB
|
||||
{ 4, 5, 4, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_5x4_sRGB
|
||||
{ 4, 5, 5, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_5x5_sRGB
|
||||
{ 4, 6, 5, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_6x5_sRGB
|
||||
{ 4, 6, 6, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_6x6_sRGB
|
||||
{ 4, 8, 5, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x5_sRGB
|
||||
{ 4, 8, 6, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x6_sRGB
|
||||
{ 4, 8, 8, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_8x8_sRGB
|
||||
{ 4, 8, 5, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x5_sRGB
|
||||
{ 4, 10, 6, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x6_sRGB
|
||||
{ 4, 10, 8, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x8_sRGB
|
||||
{ 4, 10, 10, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_10x10_sRGB
|
||||
{ 4, 12, 10, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_12x10_sRGB
|
||||
{ 4, 12, 12, 1, true, false, false, true, true, PIXELFORMATTYPE_UNORM }, // PIXELFORMAT_ASTC_12x12_sRGB
|
||||
};
|
||||
|
||||
static_assert(sizeof(formatInfo) / sizeof(PixelFormatInfo) == PIXELFORMAT_MAX_ENUM, "Update the formatInfo array when adding or removing a PixelFormat");
|
||||
@@ -155,19 +180,19 @@ static StringMap<PixelFormat, PIXELFORMAT_MAX_ENUM>::Entry formatEntries[] =
|
||||
{ "rg32i", PIXELFORMAT_RG32_INT },
|
||||
{ "rg32ui", PIXELFORMAT_RG32_UINT },
|
||||
|
||||
{ "rgba8", PIXELFORMAT_RGBA8_UNORM },
|
||||
{ "srgba8", PIXELFORMAT_RGBA8_UNORM_sRGB },
|
||||
{ "bgra8", PIXELFORMAT_BGRA8_UNORM },
|
||||
{ "bgra8srgb", PIXELFORMAT_BGRA8_UNORM_sRGB },
|
||||
{ "rgba8i", PIXELFORMAT_RGBA8_INT },
|
||||
{ "rgba8ui", PIXELFORMAT_RGBA8_UINT },
|
||||
{ "rgba16", PIXELFORMAT_RGBA16_UNORM },
|
||||
{ "rgba16f", PIXELFORMAT_RGBA16_FLOAT },
|
||||
{ "rgba16i", PIXELFORMAT_RGBA16_INT },
|
||||
{ "rgba16ui", PIXELFORMAT_RGBA16_UINT },
|
||||
{ "rgba32f", PIXELFORMAT_RGBA32_FLOAT },
|
||||
{ "rgba32i", PIXELFORMAT_RGBA32_INT },
|
||||
{ "rgba32ui", PIXELFORMAT_RGBA32_UINT },
|
||||
{ "rgba8", PIXELFORMAT_RGBA8_UNORM },
|
||||
{ "srgba8", PIXELFORMAT_RGBA8_sRGB },
|
||||
{ "bgra8", PIXELFORMAT_BGRA8_UNORM },
|
||||
{ "bgra8srgb", PIXELFORMAT_BGRA8_sRGB },
|
||||
{ "rgba8i", PIXELFORMAT_RGBA8_INT },
|
||||
{ "rgba8ui", PIXELFORMAT_RGBA8_UINT },
|
||||
{ "rgba16", PIXELFORMAT_RGBA16_UNORM },
|
||||
{ "rgba16f", PIXELFORMAT_RGBA16_FLOAT },
|
||||
{ "rgba16i", PIXELFORMAT_RGBA16_INT },
|
||||
{ "rgba16ui", PIXELFORMAT_RGBA16_UINT },
|
||||
{ "rgba32f", PIXELFORMAT_RGBA32_FLOAT },
|
||||
{ "rgba32i", PIXELFORMAT_RGBA32_INT },
|
||||
{ "rgba32ui", PIXELFORMAT_RGBA32_UINT },
|
||||
|
||||
{ "rgba4", PIXELFORMAT_RGBA4_UNORM },
|
||||
{ "rgb5a1", PIXELFORMAT_RGB5A1_UNORM },
|
||||
@@ -182,43 +207,70 @@ static StringMap<PixelFormat, PIXELFORMAT_MAX_ENUM>::Entry formatEntries[] =
|
||||
{ "depth24stencil8", PIXELFORMAT_DEPTH24_UNORM_STENCIL8 },
|
||||
{ "depth32fstencil8", PIXELFORMAT_DEPTH32_FLOAT_STENCIL8 },
|
||||
|
||||
{ "DXT1", PIXELFORMAT_DXT1_UNORM },
|
||||
{ "DXT3", PIXELFORMAT_DXT3_UNORM },
|
||||
{ "DXT5", PIXELFORMAT_DXT5_UNORM },
|
||||
{ "BC4", PIXELFORMAT_BC4_UNORM },
|
||||
{ "BC4s", PIXELFORMAT_BC4_SNORM },
|
||||
{ "BC5", PIXELFORMAT_BC5_UNORM },
|
||||
{ "BC5s", PIXELFORMAT_BC5_SNORM },
|
||||
{ "BC6h", PIXELFORMAT_BC6H_UFLOAT },
|
||||
{ "BC6hs", PIXELFORMAT_BC6H_FLOAT },
|
||||
{ "BC7", PIXELFORMAT_BC7_UNORM },
|
||||
{ "PVR1rgb2", PIXELFORMAT_PVR1_RGB2_UNORM },
|
||||
{ "PVR1rgb4", PIXELFORMAT_PVR1_RGB4_UNORM },
|
||||
{ "PVR1rgba2", PIXELFORMAT_PVR1_RGBA2_UNORM },
|
||||
{ "PVR1rgba4", PIXELFORMAT_PVR1_RGBA4_UNORM },
|
||||
{ "ETC1", PIXELFORMAT_ETC1_UNORM },
|
||||
{ "ETC2rgb", PIXELFORMAT_ETC2_RGB_UNORM },
|
||||
{ "ETC2rgba", PIXELFORMAT_ETC2_RGBA_UNORM },
|
||||
{ "ETC2rgba1", PIXELFORMAT_ETC2_RGBA1_UNORM },
|
||||
{ "EACr", PIXELFORMAT_EAC_R_UNORM },
|
||||
{ "EACrs", PIXELFORMAT_EAC_R_SNORM },
|
||||
{ "EACrg", PIXELFORMAT_EAC_RG_UNORM },
|
||||
{ "EACrgs", PIXELFORMAT_EAC_RG_SNORM },
|
||||
{ "DXT1", PIXELFORMAT_DXT1_UNORM },
|
||||
{ "DXT1srgb", PIXELFORMAT_DXT1_sRGB },
|
||||
{ "DXT3", PIXELFORMAT_DXT3_UNORM },
|
||||
{ "DXT3srgb", PIXELFORMAT_DXT3_sRGB },
|
||||
{ "DXT5", PIXELFORMAT_DXT5_UNORM },
|
||||
{ "DXT5srgb", PIXELFORMAT_DXT5_sRGB },
|
||||
{ "BC4", PIXELFORMAT_BC4_UNORM },
|
||||
{ "BC4s", PIXELFORMAT_BC4_SNORM },
|
||||
{ "BC5", PIXELFORMAT_BC5_UNORM },
|
||||
{ "BC5s", PIXELFORMAT_BC5_SNORM },
|
||||
{ "BC6h", PIXELFORMAT_BC6H_UFLOAT },
|
||||
{ "BC6hs", PIXELFORMAT_BC6H_FLOAT },
|
||||
{ "BC7", PIXELFORMAT_BC7_UNORM },
|
||||
{ "BC7srgb", PIXELFORMAT_BC7_sRGB },
|
||||
|
||||
{ "ASTC4x4", PIXELFORMAT_ASTC_4x4 },
|
||||
{ "ASTC5x4", PIXELFORMAT_ASTC_5x4 },
|
||||
{ "ASTC5x5", PIXELFORMAT_ASTC_5x5 },
|
||||
{ "ASTC6x5", PIXELFORMAT_ASTC_6x5 },
|
||||
{ "ASTC6x6", PIXELFORMAT_ASTC_6x6 },
|
||||
{ "ASTC8x5", PIXELFORMAT_ASTC_8x5 },
|
||||
{ "ASTC8x6", PIXELFORMAT_ASTC_8x6 },
|
||||
{ "ASTC8x8", PIXELFORMAT_ASTC_8x8 },
|
||||
{ "ASTC10x5", PIXELFORMAT_ASTC_10x5 },
|
||||
{ "ASTC10x6", PIXELFORMAT_ASTC_10x6 },
|
||||
{ "ASTC10x8", PIXELFORMAT_ASTC_10x8 },
|
||||
{ "ASTC10x10", PIXELFORMAT_ASTC_10x10 },
|
||||
{ "ASTC12x10", PIXELFORMAT_ASTC_12x10 },
|
||||
{ "ASTC12x12", PIXELFORMAT_ASTC_12x12 },
|
||||
{ "PVR1rgb2", PIXELFORMAT_PVR1_RGB2_UNORM },
|
||||
{ "PVR1rgb2srgb", PIXELFORMAT_PVR1_RGB2_sRGB },
|
||||
{ "PVR1rgb4", PIXELFORMAT_PVR1_RGB4_UNORM },
|
||||
{ "PVR1rgb4srgb", PIXELFORMAT_PVR1_RGB4_sRGB },
|
||||
{ "PVR1rgba2", PIXELFORMAT_PVR1_RGBA2_UNORM },
|
||||
{ "PVR1rgba2srgb", PIXELFORMAT_PVR1_RGBA2_sRGB },
|
||||
{ "PVR1rgba4", PIXELFORMAT_PVR1_RGBA4_UNORM },
|
||||
{ "PVR1rgba4srgb", PIXELFORMAT_PVR1_RGBA4_sRGB },
|
||||
|
||||
{ "ETC1", PIXELFORMAT_ETC1_UNORM },
|
||||
{ "ETC2rgb", PIXELFORMAT_ETC2_RGB_UNORM },
|
||||
{ "ETC2srgb", PIXELFORMAT_ETC2_RGB_sRGB },
|
||||
{ "ETC2rgba", PIXELFORMAT_ETC2_RGBA_UNORM },
|
||||
{ "ETC2srgba", PIXELFORMAT_ETC2_RGBA_sRGB },
|
||||
{ "ETC2rgba1", PIXELFORMAT_ETC2_RGBA1_UNORM },
|
||||
{ "ETC2srgba1", PIXELFORMAT_ETC2_RGBA1_sRGB },
|
||||
{ "EACr", PIXELFORMAT_EAC_R_UNORM },
|
||||
{ "EACrs", PIXELFORMAT_EAC_R_SNORM },
|
||||
{ "EACrg", PIXELFORMAT_EAC_RG_UNORM },
|
||||
{ "EACrgs", PIXELFORMAT_EAC_RG_SNORM },
|
||||
|
||||
{ "ASTC4x4", PIXELFORMAT_ASTC_4x4_UNORM },
|
||||
{ "ASTC5x4", PIXELFORMAT_ASTC_5x4_UNORM },
|
||||
{ "ASTC5x5", PIXELFORMAT_ASTC_5x5_UNORM },
|
||||
{ "ASTC6x5", PIXELFORMAT_ASTC_6x5_UNORM },
|
||||
{ "ASTC6x6", PIXELFORMAT_ASTC_6x6_UNORM },
|
||||
{ "ASTC8x5", PIXELFORMAT_ASTC_8x5_UNORM },
|
||||
{ "ASTC8x6", PIXELFORMAT_ASTC_8x6_UNORM },
|
||||
{ "ASTC8x8", PIXELFORMAT_ASTC_8x8_UNORM },
|
||||
{ "ASTC10x5", PIXELFORMAT_ASTC_10x5_UNORM },
|
||||
{ "ASTC10x6", PIXELFORMAT_ASTC_10x6_UNORM },
|
||||
{ "ASTC10x8", PIXELFORMAT_ASTC_10x8_UNORM },
|
||||
{ "ASTC10x10", PIXELFORMAT_ASTC_10x10_UNORM },
|
||||
{ "ASTC12x10", PIXELFORMAT_ASTC_12x10_UNORM },
|
||||
{ "ASTC12x12", PIXELFORMAT_ASTC_12x12_UNORM },
|
||||
{ "ASTC4x4srgb", PIXELFORMAT_ASTC_4x4_sRGB },
|
||||
{ "ASTC5x4srgb", PIXELFORMAT_ASTC_5x4_sRGB },
|
||||
{ "ASTC5x5srgb", PIXELFORMAT_ASTC_5x5_sRGB },
|
||||
{ "ASTC6x5srgb", PIXELFORMAT_ASTC_6x5_sRGB },
|
||||
{ "ASTC6x6srgb", PIXELFORMAT_ASTC_6x6_sRGB },
|
||||
{ "ASTC8x5srgb", PIXELFORMAT_ASTC_8x5_sRGB },
|
||||
{ "ASTC8x6srgb", PIXELFORMAT_ASTC_8x6_sRGB },
|
||||
{ "ASTC8x8srgb", PIXELFORMAT_ASTC_8x8_sRGB },
|
||||
{ "ASTC10x5srgb", PIXELFORMAT_ASTC_10x5_sRGB },
|
||||
{ "ASTC10x6srgb", PIXELFORMAT_ASTC_10x6_sRGB },
|
||||
{ "ASTC10x8srgb", PIXELFORMAT_ASTC_10x8_sRGB },
|
||||
{ "ASTC10x10srgb", PIXELFORMAT_ASTC_10x10_sRGB },
|
||||
{ "ASTC12x10srgb", PIXELFORMAT_ASTC_12x10_sRGB },
|
||||
{ "ASTC12x12srgb", PIXELFORMAT_ASTC_12x12_sRGB },
|
||||
};
|
||||
|
||||
static_assert(sizeof(formatEntries) / sizeof(formatEntries[0]) == (size_t) PIXELFORMAT_MAX_ENUM, "pixel format string map is missing entries!");
|
||||
@@ -275,7 +327,7 @@ bool isPixelFormatStencil(PixelFormat format)
|
||||
|
||||
bool isPixelFormatSRGB(PixelFormat format)
|
||||
{
|
||||
return format == PIXELFORMAT_RGBA8_UNORM_sRGB || format == PIXELFORMAT_BGRA8_UNORM_sRGB;
|
||||
return formatInfo[format].sRGB;
|
||||
}
|
||||
|
||||
bool isPixelFormatInteger(PixelFormat format)
|
||||
@@ -286,20 +338,65 @@ bool isPixelFormatInteger(PixelFormat format)
|
||||
|
||||
PixelFormat getSRGBPixelFormat(PixelFormat format)
|
||||
{
|
||||
if (format == PIXELFORMAT_RGBA8_UNORM)
|
||||
return PIXELFORMAT_RGBA8_UNORM_sRGB;
|
||||
else if (format == PIXELFORMAT_BGRA8_UNORM)
|
||||
return PIXELFORMAT_BGRA8_UNORM_sRGB;
|
||||
return format;
|
||||
switch (format)
|
||||
{
|
||||
case PIXELFORMAT_RGBA8_UNORM: return PIXELFORMAT_RGBA8_sRGB;
|
||||
case PIXELFORMAT_BGRA8_UNORM: return PIXELFORMAT_BGRA8_sRGB;
|
||||
case PIXELFORMAT_PVR1_RGB2_UNORM: return PIXELFORMAT_PVR1_RGB2_sRGB;
|
||||
case PIXELFORMAT_PVR1_RGB4_UNORM: return PIXELFORMAT_PVR1_RGB4_sRGB;
|
||||
case PIXELFORMAT_PVR1_RGBA2_UNORM: return PIXELFORMAT_PVR1_RGBA2_sRGB;
|
||||
case PIXELFORMAT_PVR1_RGBA4_UNORM: return PIXELFORMAT_PVR1_RGBA4_sRGB;
|
||||
case PIXELFORMAT_ETC1_UNORM: return PIXELFORMAT_ETC2_RGB_sRGB; // ETC2 can load ETC1 data.
|
||||
case PIXELFORMAT_ETC2_RGB_UNORM: return PIXELFORMAT_ETC2_RGB_sRGB;
|
||||
case PIXELFORMAT_ETC2_RGBA_UNORM: return PIXELFORMAT_ETC2_RGBA_sRGB;
|
||||
case PIXELFORMAT_ETC2_RGBA1_UNORM: return PIXELFORMAT_ETC2_RGBA1_sRGB;
|
||||
case PIXELFORMAT_ASTC_4x4_UNORM: return PIXELFORMAT_ASTC_4x4_sRGB;
|
||||
case PIXELFORMAT_ASTC_5x4_UNORM: return PIXELFORMAT_ASTC_5x4_sRGB;
|
||||
case PIXELFORMAT_ASTC_5x5_UNORM: return PIXELFORMAT_ASTC_5x5_sRGB;
|
||||
case PIXELFORMAT_ASTC_6x5_UNORM: return PIXELFORMAT_ASTC_6x5_sRGB;
|
||||
case PIXELFORMAT_ASTC_6x6_UNORM: return PIXELFORMAT_ASTC_6x6_sRGB;
|
||||
case PIXELFORMAT_ASTC_8x5_UNORM: return PIXELFORMAT_ASTC_8x5_sRGB;
|
||||
case PIXELFORMAT_ASTC_8x6_UNORM: return PIXELFORMAT_ASTC_8x6_sRGB;
|
||||
case PIXELFORMAT_ASTC_8x8_UNORM: return PIXELFORMAT_ASTC_8x8_sRGB;
|
||||
case PIXELFORMAT_ASTC_10x5_UNORM: return PIXELFORMAT_ASTC_10x5_sRGB;
|
||||
case PIXELFORMAT_ASTC_10x6_UNORM: return PIXELFORMAT_ASTC_10x6_sRGB;
|
||||
case PIXELFORMAT_ASTC_10x8_UNORM: return PIXELFORMAT_ASTC_10x8_sRGB;
|
||||
case PIXELFORMAT_ASTC_10x10_UNORM: return PIXELFORMAT_ASTC_10x10_sRGB;
|
||||
case PIXELFORMAT_ASTC_12x10_UNORM: return PIXELFORMAT_ASTC_12x10_sRGB;
|
||||
case PIXELFORMAT_ASTC_12x12_UNORM: return PIXELFORMAT_ASTC_12x12_sRGB;
|
||||
default: return format;
|
||||
}
|
||||
}
|
||||
|
||||
PixelFormat getLinearPixelFormat(PixelFormat format)
|
||||
{
|
||||
if (format == PIXELFORMAT_RGBA8_UNORM_sRGB)
|
||||
return PIXELFORMAT_RGBA8_UNORM;
|
||||
else if (format == PIXELFORMAT_BGRA8_UNORM_sRGB)
|
||||
return PIXELFORMAT_BGRA8_UNORM;
|
||||
return format;
|
||||
switch (format)
|
||||
{
|
||||
case PIXELFORMAT_RGBA8_sRGB: return PIXELFORMAT_RGBA8_UNORM;
|
||||
case PIXELFORMAT_BGRA8_sRGB: return PIXELFORMAT_BGRA8_UNORM;
|
||||
case PIXELFORMAT_PVR1_RGB2_sRGB: return PIXELFORMAT_PVR1_RGB2_UNORM;
|
||||
case PIXELFORMAT_PVR1_RGB4_sRGB: return PIXELFORMAT_PVR1_RGB4_UNORM;
|
||||
case PIXELFORMAT_PVR1_RGBA2_sRGB: return PIXELFORMAT_PVR1_RGBA2_UNORM;
|
||||
case PIXELFORMAT_PVR1_RGBA4_sRGB: return PIXELFORMAT_PVR1_RGBA4_UNORM;
|
||||
case PIXELFORMAT_ETC2_RGB_sRGB: return PIXELFORMAT_ETC2_RGB_UNORM;
|
||||
case PIXELFORMAT_ETC2_RGBA_sRGB: return PIXELFORMAT_ETC2_RGBA_UNORM;
|
||||
case PIXELFORMAT_ETC2_RGBA1_sRGB: return PIXELFORMAT_ETC2_RGBA1_UNORM;
|
||||
case PIXELFORMAT_ASTC_4x4_sRGB: return PIXELFORMAT_ASTC_4x4_UNORM;
|
||||
case PIXELFORMAT_ASTC_5x4_sRGB: return PIXELFORMAT_ASTC_5x4_UNORM;
|
||||
case PIXELFORMAT_ASTC_5x5_sRGB: return PIXELFORMAT_ASTC_5x5_UNORM;
|
||||
case PIXELFORMAT_ASTC_6x5_sRGB: return PIXELFORMAT_ASTC_6x5_UNORM;
|
||||
case PIXELFORMAT_ASTC_6x6_sRGB: return PIXELFORMAT_ASTC_6x6_UNORM;
|
||||
case PIXELFORMAT_ASTC_8x5_sRGB: return PIXELFORMAT_ASTC_8x5_UNORM;
|
||||
case PIXELFORMAT_ASTC_8x6_sRGB: return PIXELFORMAT_ASTC_8x6_UNORM;
|
||||
case PIXELFORMAT_ASTC_8x8_sRGB: return PIXELFORMAT_ASTC_8x8_UNORM;
|
||||
case PIXELFORMAT_ASTC_10x5_sRGB: return PIXELFORMAT_ASTC_10x5_UNORM;
|
||||
case PIXELFORMAT_ASTC_10x6_sRGB: return PIXELFORMAT_ASTC_10x6_UNORM;
|
||||
case PIXELFORMAT_ASTC_10x8_sRGB: return PIXELFORMAT_ASTC_10x8_UNORM;
|
||||
case PIXELFORMAT_ASTC_10x10_sRGB: return PIXELFORMAT_ASTC_10x10_UNORM;
|
||||
case PIXELFORMAT_ASTC_12x10_sRGB: return PIXELFORMAT_ASTC_12x10_UNORM;
|
||||
case PIXELFORMAT_ASTC_12x12_sRGB: return PIXELFORMAT_ASTC_12x12_UNORM;
|
||||
default: return format;
|
||||
}
|
||||
}
|
||||
|
||||
size_t getPixelFormatBlockSize(PixelFormat format)
|
||||
|
||||
+45
-16
@@ -60,9 +60,9 @@ enum PixelFormat
|
||||
|
||||
// 4-channel normal formats
|
||||
PIXELFORMAT_RGBA8_UNORM,
|
||||
PIXELFORMAT_RGBA8_UNORM_sRGB,
|
||||
PIXELFORMAT_RGBA8_sRGB,
|
||||
PIXELFORMAT_BGRA8_UNORM,
|
||||
PIXELFORMAT_BGRA8_UNORM_sRGB,
|
||||
PIXELFORMAT_BGRA8_sRGB,
|
||||
PIXELFORMAT_RGBA8_INT,
|
||||
PIXELFORMAT_RGBA8_UINT,
|
||||
PIXELFORMAT_RGBA16_UNORM,
|
||||
@@ -90,8 +90,11 @@ enum PixelFormat
|
||||
|
||||
// compressed formats
|
||||
PIXELFORMAT_DXT1_UNORM,
|
||||
PIXELFORMAT_DXT1_sRGB,
|
||||
PIXELFORMAT_DXT3_UNORM,
|
||||
PIXELFORMAT_DXT3_sRGB,
|
||||
PIXELFORMAT_DXT5_UNORM,
|
||||
PIXELFORMAT_DXT5_sRGB,
|
||||
PIXELFORMAT_BC4_UNORM,
|
||||
PIXELFORMAT_BC4_SNORM,
|
||||
PIXELFORMAT_BC5_UNORM,
|
||||
@@ -99,32 +102,57 @@ enum PixelFormat
|
||||
PIXELFORMAT_BC6H_UFLOAT,
|
||||
PIXELFORMAT_BC6H_FLOAT,
|
||||
PIXELFORMAT_BC7_UNORM,
|
||||
PIXELFORMAT_BC7_sRGB,
|
||||
|
||||
PIXELFORMAT_PVR1_RGB2_UNORM,
|
||||
PIXELFORMAT_PVR1_RGB2_sRGB,
|
||||
PIXELFORMAT_PVR1_RGB4_UNORM,
|
||||
PIXELFORMAT_PVR1_RGB4_sRGB,
|
||||
PIXELFORMAT_PVR1_RGBA2_UNORM,
|
||||
PIXELFORMAT_PVR1_RGBA2_sRGB,
|
||||
PIXELFORMAT_PVR1_RGBA4_UNORM,
|
||||
PIXELFORMAT_PVR1_RGBA4_sRGB,
|
||||
|
||||
PIXELFORMAT_ETC1_UNORM,
|
||||
PIXELFORMAT_ETC2_RGB_UNORM,
|
||||
PIXELFORMAT_ETC2_RGB_sRGB,
|
||||
PIXELFORMAT_ETC2_RGBA_UNORM,
|
||||
PIXELFORMAT_ETC2_RGBA_sRGB,
|
||||
PIXELFORMAT_ETC2_RGBA1_UNORM,
|
||||
PIXELFORMAT_ETC2_RGBA1_sRGB,
|
||||
PIXELFORMAT_EAC_R_UNORM,
|
||||
PIXELFORMAT_EAC_R_SNORM,
|
||||
PIXELFORMAT_EAC_RG_UNORM,
|
||||
PIXELFORMAT_EAC_RG_SNORM,
|
||||
PIXELFORMAT_ASTC_4x4,
|
||||
PIXELFORMAT_ASTC_5x4,
|
||||
PIXELFORMAT_ASTC_5x5,
|
||||
PIXELFORMAT_ASTC_6x5,
|
||||
PIXELFORMAT_ASTC_6x6,
|
||||
PIXELFORMAT_ASTC_8x5,
|
||||
PIXELFORMAT_ASTC_8x6,
|
||||
PIXELFORMAT_ASTC_8x8,
|
||||
PIXELFORMAT_ASTC_10x5,
|
||||
PIXELFORMAT_ASTC_10x6,
|
||||
PIXELFORMAT_ASTC_10x8,
|
||||
PIXELFORMAT_ASTC_10x10,
|
||||
PIXELFORMAT_ASTC_12x10,
|
||||
PIXELFORMAT_ASTC_12x12,
|
||||
|
||||
PIXELFORMAT_ASTC_4x4_UNORM,
|
||||
PIXELFORMAT_ASTC_5x4_UNORM,
|
||||
PIXELFORMAT_ASTC_5x5_UNORM,
|
||||
PIXELFORMAT_ASTC_6x5_UNORM,
|
||||
PIXELFORMAT_ASTC_6x6_UNORM,
|
||||
PIXELFORMAT_ASTC_8x5_UNORM,
|
||||
PIXELFORMAT_ASTC_8x6_UNORM,
|
||||
PIXELFORMAT_ASTC_8x8_UNORM,
|
||||
PIXELFORMAT_ASTC_10x5_UNORM,
|
||||
PIXELFORMAT_ASTC_10x6_UNORM,
|
||||
PIXELFORMAT_ASTC_10x8_UNORM,
|
||||
PIXELFORMAT_ASTC_10x10_UNORM,
|
||||
PIXELFORMAT_ASTC_12x10_UNORM,
|
||||
PIXELFORMAT_ASTC_12x12_UNORM,
|
||||
PIXELFORMAT_ASTC_4x4_sRGB,
|
||||
PIXELFORMAT_ASTC_5x4_sRGB,
|
||||
PIXELFORMAT_ASTC_5x5_sRGB,
|
||||
PIXELFORMAT_ASTC_6x5_sRGB,
|
||||
PIXELFORMAT_ASTC_6x6_sRGB,
|
||||
PIXELFORMAT_ASTC_8x5_sRGB,
|
||||
PIXELFORMAT_ASTC_8x6_sRGB,
|
||||
PIXELFORMAT_ASTC_8x8_sRGB,
|
||||
PIXELFORMAT_ASTC_10x5_sRGB,
|
||||
PIXELFORMAT_ASTC_10x6_sRGB,
|
||||
PIXELFORMAT_ASTC_10x8_sRGB,
|
||||
PIXELFORMAT_ASTC_10x10_sRGB,
|
||||
PIXELFORMAT_ASTC_12x10_sRGB,
|
||||
PIXELFORMAT_ASTC_12x12_sRGB,
|
||||
|
||||
PIXELFORMAT_MAX_ENUM
|
||||
};
|
||||
@@ -149,6 +177,7 @@ struct PixelFormatInfo
|
||||
bool depth;
|
||||
bool stencil;
|
||||
bool compressed;
|
||||
bool sRGB;
|
||||
PixelFormatType dataType;
|
||||
};
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ int w_ByteData_setString(lua_State *L)
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
if (offset < 0 || offset + size > (int64) t->getSize())
|
||||
if (offset < 0 || offset + (int64) size > (int64) t->getSize())
|
||||
return luaL_error(L, "The given string offset and size don't fit within the Data's size.");
|
||||
|
||||
memcpy((char *) t->getData() + (size_t) offset, str, size);
|
||||
|
||||
@@ -45,14 +45,9 @@ Font::Font()
|
||||
defaultFontData.set(new data::ByteData(fontdata, rawsize, true), Acquire::NORETAIN);
|
||||
}
|
||||
|
||||
Rasterizer *Font::newTrueTypeRasterizer(int size, TrueTypeRasterizer::Hinting hinting)
|
||||
Rasterizer *Font::newTrueTypeRasterizer(int size, const TrueTypeRasterizer::Settings &settings)
|
||||
{
|
||||
return newTrueTypeRasterizer(defaultFontData.get(), size, hinting);
|
||||
}
|
||||
|
||||
Rasterizer *Font::newTrueTypeRasterizer(int size, float dpiscale, TrueTypeRasterizer::Hinting hinting)
|
||||
{
|
||||
return newTrueTypeRasterizer(defaultFontData.get(), size, dpiscale, hinting);
|
||||
return newTrueTypeRasterizer(defaultFontData.get(), size, settings);
|
||||
}
|
||||
|
||||
Rasterizer *Font::newBMFontRasterizer(love::filesystem::FileData *fontdef, const std::vector<image::ImageData *> &images, float dpiscale)
|
||||
@@ -78,12 +73,7 @@ Rasterizer *Font::newImageRasterizer(love::image::ImageData *data, const std::st
|
||||
throw love::Exception("UTF-8 decoding error: %s", e.what());
|
||||
}
|
||||
|
||||
return newImageRasterizer(data, &glyphs[0], (int) glyphs.size(), extraspacing, dpiscale);
|
||||
}
|
||||
|
||||
Rasterizer *Font::newImageRasterizer(love::image::ImageData *data, uint32 *glyphs, int numglyphs, int extraspacing, float dpiscale)
|
||||
{
|
||||
return new ImageRasterizer(data, glyphs, numglyphs, extraspacing, dpiscale);
|
||||
return new ImageRasterizer(data, glyphs.data(), (int) glyphs.size(), extraspacing, dpiscale);
|
||||
}
|
||||
|
||||
GlyphData *Font::newGlyphData(Rasterizer *r, const std::string &text)
|
||||
|
||||
@@ -48,15 +48,12 @@ public:
|
||||
|
||||
virtual Rasterizer *newRasterizer(love::filesystem::FileData *data) = 0;
|
||||
|
||||
virtual Rasterizer *newTrueTypeRasterizer(int size, TrueTypeRasterizer::Hinting hinting);
|
||||
virtual Rasterizer *newTrueTypeRasterizer(int size, float dpiscale, TrueTypeRasterizer::Hinting hinting);
|
||||
virtual Rasterizer *newTrueTypeRasterizer(love::Data *data, int size, TrueTypeRasterizer::Hinting hinting) = 0;
|
||||
virtual Rasterizer *newTrueTypeRasterizer(love::Data *data, int size, float dpiscale, TrueTypeRasterizer::Hinting hinting) = 0;
|
||||
Rasterizer *newTrueTypeRasterizer(int size, const TrueTypeRasterizer::Settings &settings);
|
||||
virtual Rasterizer *newTrueTypeRasterizer(love::Data *data, int size, const TrueTypeRasterizer::Settings &settings) = 0;
|
||||
|
||||
virtual Rasterizer *newBMFontRasterizer(love::filesystem::FileData *fontdef, const std::vector<image::ImageData *> &images, float dpiscale);
|
||||
|
||||
virtual Rasterizer *newImageRasterizer(love::image::ImageData *data, const std::string &glyphs, int extraspacing, float dpiscale);
|
||||
virtual Rasterizer *newImageRasterizer(love::image::ImageData *data, uint32 *glyphs, int length, int extraspacing, float dpiscale);
|
||||
|
||||
virtual GlyphData *newGlyphData(Rasterizer *r, const std::string &glyph);
|
||||
virtual GlyphData *newGlyphData(Rasterizer *r, uint32 glyph);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
// LOVE
|
||||
#include "Rasterizer.h"
|
||||
#include "common/StringMap.h"
|
||||
#include "common/Optional.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
@@ -44,6 +45,12 @@ public:
|
||||
HINTING_MAX_ENUM
|
||||
};
|
||||
|
||||
struct Settings
|
||||
{
|
||||
Hinting hinting = HINTING_NORMAL;
|
||||
OptionalFloat dpiScale;
|
||||
};
|
||||
|
||||
virtual ~TrueTypeRasterizer() {}
|
||||
|
||||
static bool getConstant(const char *in, Hinting &out);
|
||||
|
||||
@@ -49,26 +49,21 @@ Font::~Font()
|
||||
Rasterizer *Font::newRasterizer(love::filesystem::FileData *data)
|
||||
{
|
||||
if (TrueTypeRasterizer::accepts(library, data))
|
||||
return newTrueTypeRasterizer(data, 12, TrueTypeRasterizer::HINTING_NORMAL);
|
||||
return newTrueTypeRasterizer(data, 12, font::TrueTypeRasterizer::Settings());
|
||||
else if (BMFontRasterizer::accepts(data))
|
||||
return newBMFontRasterizer(data, {}, 1.0f);
|
||||
|
||||
throw love::Exception("Invalid font file: %s", data->getFilename().c_str());
|
||||
}
|
||||
|
||||
Rasterizer *Font::newTrueTypeRasterizer(love::Data *data, int size, TrueTypeRasterizer::Hinting hinting)
|
||||
Rasterizer *Font::newTrueTypeRasterizer(love::Data *data, int size, const font::TrueTypeRasterizer::Settings &settings)
|
||||
{
|
||||
float dpiscale = 1.0f;
|
||||
float defaultdpiscale = 1.0f;
|
||||
auto window = Module::getInstance<window::Window>(Module::M_WINDOW);
|
||||
if (window != nullptr)
|
||||
dpiscale = window->getDPIScale();
|
||||
defaultdpiscale = window->getDPIScale();
|
||||
|
||||
return newTrueTypeRasterizer(data, size, dpiscale, hinting);
|
||||
}
|
||||
|
||||
Rasterizer *Font::newTrueTypeRasterizer(love::Data *data, int size, float dpiscale, TrueTypeRasterizer::Hinting hinting)
|
||||
{
|
||||
return new TrueTypeRasterizer(library, data, size, dpiscale, hinting);
|
||||
return new TrueTypeRasterizer(library, data, size, settings, defaultdpiscale);
|
||||
}
|
||||
|
||||
const char *Font::getName() const
|
||||
|
||||
@@ -45,8 +45,7 @@ public:
|
||||
|
||||
// Implements Font
|
||||
Rasterizer *newRasterizer(love::filesystem::FileData *data) override;
|
||||
Rasterizer *newTrueTypeRasterizer(love::Data *data, int size, TrueTypeRasterizer::Hinting hinting) override;
|
||||
Rasterizer *newTrueTypeRasterizer(love::Data *data, int size, float dpiscale, TrueTypeRasterizer::Hinting hinting) override;
|
||||
Rasterizer *newTrueTypeRasterizer(love::Data *data, int size, const font::TrueTypeRasterizer::Settings &settings) override;
|
||||
|
||||
// Implement Module
|
||||
const char *getName() const override;
|
||||
|
||||
@@ -153,18 +153,18 @@ void HarfbuzzShaper::computeBufferRanges(const ColoredCodepoints &codepoints, Ra
|
||||
|
||||
hb_shape(hbFonts[rasti], hbb, nullptr, 0);
|
||||
|
||||
int glyphcount = (int)hb_buffer_get_length(hbb);
|
||||
size_t glyphcount = (size_t)hb_buffer_get_length(hbb);
|
||||
const hb_glyph_info_t *glyphinfos = hb_buffer_get_glyph_infos(hbb, nullptr);
|
||||
hb_direction_t direction = hb_buffer_get_direction(hbb);
|
||||
|
||||
fallbackranges.clear();
|
||||
|
||||
for (int i = 0; i < glyphcount; i++)
|
||||
for (size_t i = 0; i < glyphcount; i++)
|
||||
{
|
||||
if (isValidGlyph(glyphinfos[i].codepoint, codepoints.cps, glyphinfos[i].cluster))
|
||||
{
|
||||
if (bufferranges.empty() || bufferranges.back().index != rasti || bufferranges.back().range.getMax() + 1 != i)
|
||||
bufferranges.push_back({(int)rasti, (int)glyphinfos[i].cluster, Range(i, 1)});
|
||||
bufferranges.push_back({rasti, (int)glyphinfos[i].cluster, Range(i, 1)});
|
||||
else
|
||||
bufferranges.back().range.last++;
|
||||
}
|
||||
@@ -247,7 +247,7 @@ void HarfbuzzShaper::computeGlyphPositions(const ColoredCodepoints &codepoints,
|
||||
// TODO: this doesn't handle situations where the user inserted a color
|
||||
// change in the middle of some characters that get combined into a single
|
||||
// cluster.
|
||||
if (colors && colorindex < ncolors && codepoints.colors[colorindex].index == info.cluster)
|
||||
if (colors && colorindex < ncolors && codepoints.colors[colorindex].index == (int)info.cluster)
|
||||
{
|
||||
colorToAdd.set(codepoints.colors[colorindex].color);
|
||||
colorindex++;
|
||||
@@ -273,7 +273,7 @@ void HarfbuzzShaper::computeGlyphPositions(const ColoredCodepoints &codepoints,
|
||||
continue;
|
||||
|
||||
// This is a glyph index at this point, despite the name.
|
||||
GlyphIndex gindex = { (int) info.codepoint, bufferrange.index };
|
||||
GlyphIndex gindex = { (int) info.codepoint, (int)bufferrange.index };
|
||||
|
||||
if (clustercodepoint == '\t' && isUsingSpacesForTab())
|
||||
{
|
||||
@@ -390,7 +390,7 @@ int HarfbuzzShaper::computeWordWrapIndex(const ColoredCodepoints &codepoints, Ra
|
||||
if (newwidth > wraplimit)
|
||||
{
|
||||
// If this is the first character, wrap from the next one instead of this one.
|
||||
int wrapindex = info.cluster > (int) range.first ? info.cluster : (int) range.first + 1;
|
||||
int wrapindex = (int)info.cluster > (int)range.first ? (int)info.cluster : (int)range.first + 1;
|
||||
|
||||
// Rewind to after the last seen space when wrapping.
|
||||
if (firstindexafterspace != -1)
|
||||
|
||||
@@ -53,7 +53,7 @@ private:
|
||||
|
||||
struct BufferRange
|
||||
{
|
||||
int index;
|
||||
size_t index;
|
||||
int codepointStart;
|
||||
Range range;
|
||||
};
|
||||
|
||||
@@ -33,12 +33,12 @@ namespace font
|
||||
namespace freetype
|
||||
{
|
||||
|
||||
TrueTypeRasterizer::TrueTypeRasterizer(FT_Library library, love::Data *data, int size, float dpiscale, Hinting hinting)
|
||||
TrueTypeRasterizer::TrueTypeRasterizer(FT_Library library, love::Data *data, int size, const Settings &settings, float defaultdpiscale)
|
||||
: data(data)
|
||||
, hinting(hinting)
|
||||
, hinting(settings.hinting)
|
||||
{
|
||||
this->dpiScale = dpiscale;
|
||||
size = floorf(size * dpiscale + 0.5f);
|
||||
dpiScale = settings.dpiScale.get(defaultdpiscale);
|
||||
size = floorf(size * dpiScale + 0.5f);
|
||||
|
||||
if (size <= 0)
|
||||
throw love::Exception("Invalid TrueType font size: %d", size);
|
||||
|
||||
@@ -44,7 +44,7 @@ class TrueTypeRasterizer : public love::font::TrueTypeRasterizer
|
||||
{
|
||||
public:
|
||||
|
||||
TrueTypeRasterizer(FT_Library library, love::Data *data, int size, float dpiscale, Hinting hinting);
|
||||
TrueTypeRasterizer(FT_Library library, love::Data *data, int size, const Settings &settings, float defaultdpiscale);
|
||||
virtual ~TrueTypeRasterizer();
|
||||
|
||||
// Implement Rasterizer
|
||||
|
||||
@@ -64,30 +64,65 @@ int w_newRasterizer(lua_State *L)
|
||||
}
|
||||
}
|
||||
|
||||
static TrueTypeRasterizer::Settings luax_checktruetypesettings(lua_State* L, int startidx)
|
||||
{
|
||||
TrueTypeRasterizer::Settings s;
|
||||
|
||||
if (lua_type(L, startidx) == LUA_TSTRING)
|
||||
{
|
||||
// Legacy parameters.
|
||||
const char *hintstr = lua_isnoneornil(L, startidx) ? nullptr : luaL_checkstring(L, startidx);
|
||||
if (hintstr && !TrueTypeRasterizer::getConstant(hintstr, s.hinting))
|
||||
luax_enumerror(L, "TrueType font hinting mode", TrueTypeRasterizer::getConstants(s.hinting), hintstr);
|
||||
|
||||
if (!lua_isnoneornil(L, startidx + 1))
|
||||
s.dpiScale.set((float)luaL_checknumber(L, startidx + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
luaL_checktype(L, startidx, LUA_TTABLE);
|
||||
|
||||
lua_getfield(L, startidx, "hinting");
|
||||
if (!lua_isnoneornil(L, -1))
|
||||
{
|
||||
const char *hintstr = luaL_checkstring(L, -1);
|
||||
if (!TrueTypeRasterizer::getConstant(hintstr, s.hinting))
|
||||
luax_enumerror(L, "TrueType font hinting mode", TrueTypeRasterizer::getConstants(s.hinting), hintstr);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, startidx, "dpiscale");
|
||||
if (!lua_isnoneornil(L, -1))
|
||||
s.dpiScale.set((float)luaL_checknumber(L, -1));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int w_newTrueTypeRasterizer(lua_State *L)
|
||||
{
|
||||
Rasterizer *t = nullptr;
|
||||
TrueTypeRasterizer::Hinting hinting = TrueTypeRasterizer::HINTING_NORMAL;
|
||||
|
||||
if (lua_type(L, 1) == LUA_TNUMBER || lua_isnone(L, 1))
|
||||
{
|
||||
// First argument is a number: use the default TrueType font.
|
||||
int size = (int) luaL_optinteger(L, 1, 13);
|
||||
|
||||
const char *hintstr = lua_isnoneornil(L, 2) ? nullptr : luaL_checkstring(L, 2);
|
||||
if (hintstr && !TrueTypeRasterizer::getConstant(hintstr, hinting))
|
||||
return luax_enumerror(L, "TrueType font hinting mode", TrueTypeRasterizer::getConstants(hinting), hintstr);
|
||||
TrueTypeRasterizer::Settings settings;
|
||||
if (!lua_isnoneornil(L, 2))
|
||||
settings = luax_checktruetypesettings(L, 2);
|
||||
|
||||
if (lua_isnoneornil(L, 3))
|
||||
luax_catchexcept(L, [&](){ t = instance()->newTrueTypeRasterizer(size, hinting); });
|
||||
else
|
||||
{
|
||||
float dpiscale = (float) luaL_checknumber(L, 3);
|
||||
luax_catchexcept(L, [&](){ t = instance()->newTrueTypeRasterizer(size, dpiscale, hinting); });
|
||||
}
|
||||
luax_catchexcept(L, [&](){ t = instance()->newTrueTypeRasterizer(size, settings); });
|
||||
}
|
||||
else
|
||||
{
|
||||
int size = (int) luaL_optinteger(L, 2, 12);
|
||||
|
||||
TrueTypeRasterizer::Settings settings;
|
||||
if (!lua_isnoneornil(L, 3))
|
||||
settings = luax_checktruetypesettings(L, 3);
|
||||
|
||||
love::Data *d = nullptr;
|
||||
|
||||
if (luax_istype(L, 1, love::Data::type))
|
||||
@@ -98,27 +133,10 @@ int w_newTrueTypeRasterizer(lua_State *L)
|
||||
else
|
||||
d = filesystem::luax_getfiledata(L, 1);
|
||||
|
||||
int size = (int) luaL_optinteger(L, 2, 12);
|
||||
|
||||
const char *hintstr = lua_isnoneornil(L, 3) ? nullptr : luaL_checkstring(L, 3);
|
||||
if (hintstr && !TrueTypeRasterizer::getConstant(hintstr, hinting))
|
||||
return luax_enumerror(L, "TrueType font hinting mode", TrueTypeRasterizer::getConstants(hinting), hintstr);
|
||||
|
||||
if (lua_isnoneornil(L, 4))
|
||||
{
|
||||
luax_catchexcept(L,
|
||||
[&]() { t = instance()->newTrueTypeRasterizer(d, size, hinting); },
|
||||
[&](bool) { d->release(); }
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
float dpiscale = (float) luaL_checknumber(L, 4);
|
||||
luax_catchexcept(L,
|
||||
[&]() { t = instance()->newTrueTypeRasterizer(d, size, dpiscale, hinting); },
|
||||
[&](bool) { d->release(); }
|
||||
);
|
||||
}
|
||||
luax_catchexcept(L,
|
||||
[&]() { t = instance()->newTrueTypeRasterizer(d, size, settings); },
|
||||
[&](bool) { d->release(); }
|
||||
);
|
||||
}
|
||||
|
||||
luax_pushtype(L, t);
|
||||
@@ -154,7 +172,7 @@ int w_newBMFontRasterizer(lua_State *L)
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (!lua_isnoneornil(L, 2))
|
||||
{
|
||||
convimagedata(L, 2);
|
||||
image::ImageData *id = luax_checktype<image::ImageData>(L, 2);
|
||||
|
||||
@@ -74,12 +74,12 @@ void Deprecations::draw(Graphics *gfx)
|
||||
|
||||
if (font.get() == nullptr)
|
||||
{
|
||||
auto hinting = font::TrueTypeRasterizer::HINTING_NORMAL;
|
||||
font::TrueTypeRasterizer::Settings settings;
|
||||
|
||||
if (!isGammaCorrect() && gfx->getScreenDPIScale() <= 1.0)
|
||||
hinting = font::TrueTypeRasterizer::HINTING_LIGHT;
|
||||
settings.hinting = font::TrueTypeRasterizer::HINTING_LIGHT;
|
||||
|
||||
font.set(gfx->newDefaultFont(9, hinting), Acquire::NORETAIN);
|
||||
font.set(gfx->newDefaultFont(9, settings), Acquire::NORETAIN);
|
||||
}
|
||||
|
||||
gfx->flushBatchedDraws();
|
||||
|
||||
@@ -294,13 +294,13 @@ Font *Graphics::newFont(love::font::Rasterizer *data)
|
||||
return new Font(data, states.back().defaultSamplerState);
|
||||
}
|
||||
|
||||
Font *Graphics::newDefaultFont(int size, font::TrueTypeRasterizer::Hinting hinting)
|
||||
Font *Graphics::newDefaultFont(int size, const font::TrueTypeRasterizer::Settings &settings)
|
||||
{
|
||||
auto fontmodule = Module::getInstance<font::Font>(M_FONT);
|
||||
if (!fontmodule)
|
||||
throw love::Exception("Font module has not been loaded.");
|
||||
|
||||
StrongRef<font::Rasterizer> r(fontmodule->newTrueTypeRasterizer(size, hinting), Acquire::NORETAIN);
|
||||
StrongRef<font::Rasterizer> r(fontmodule->newTrueTypeRasterizer(size, settings), Acquire::NORETAIN);
|
||||
return newFont(r.get());
|
||||
}
|
||||
|
||||
@@ -731,7 +731,10 @@ void Graphics::checkSetDefaultFont()
|
||||
|
||||
// Create a new default font if we don't have one yet.
|
||||
if (!defaultFont.get())
|
||||
defaultFont.set(newDefaultFont(13, font::TrueTypeRasterizer::HINTING_NORMAL), Acquire::NORETAIN);
|
||||
{
|
||||
font::TrueTypeRasterizer::Settings settings;
|
||||
defaultFont.set(newDefaultFont(13, settings), Acquire::NORETAIN);
|
||||
}
|
||||
|
||||
states.back().font.set(defaultFont.get());
|
||||
}
|
||||
@@ -925,7 +928,7 @@ void Graphics::setRenderTargets(const RenderTargets &rts)
|
||||
PixelFormat dsformat = PIXELFORMAT_STENCIL8;
|
||||
if (wantsdepth && wantsstencil)
|
||||
dsformat = PIXELFORMAT_DEPTH24_UNORM_STENCIL8;
|
||||
else if (wantsdepth && isPixelFormatSupported(PIXELFORMAT_DEPTH24_UNORM, PIXELFORMATUSAGEFLAGS_RENDERTARGET, false))
|
||||
else if (wantsdepth && isPixelFormatSupported(PIXELFORMAT_DEPTH24_UNORM, PIXELFORMATUSAGEFLAGS_RENDERTARGET))
|
||||
dsformat = PIXELFORMAT_DEPTH24_UNORM;
|
||||
else if (wantsdepth)
|
||||
dsformat = PIXELFORMAT_DEPTH16_UNORM;
|
||||
@@ -2389,6 +2392,22 @@ const Graphics::Capabilities &Graphics::getCapabilities() const
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
PixelFormat Graphics::getSizedFormat(PixelFormat format) const
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case PIXELFORMAT_NORMAL:
|
||||
if (isGammaCorrect())
|
||||
return PIXELFORMAT_RGBA8_sRGB;
|
||||
else
|
||||
return PIXELFORMAT_RGBA8_UNORM;
|
||||
case PIXELFORMAT_HDR:
|
||||
return PIXELFORMAT_RGBA16_FLOAT;
|
||||
default:
|
||||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
Graphics::Stats Graphics::getStats() const
|
||||
{
|
||||
Stats stats;
|
||||
|
||||
@@ -459,7 +459,7 @@ public:
|
||||
|
||||
Quad *newQuad(Quad::Viewport v, double sw, double sh);
|
||||
Font *newFont(love::font::Rasterizer *data);
|
||||
Font *newDefaultFont(int size, font::TrueTypeRasterizer::Hinting hinting);
|
||||
Font *newDefaultFont(int size, const font::TrueTypeRasterizer::Settings &settings);
|
||||
Video *newVideo(love::video::VideoStream *stream, float dpiscale);
|
||||
|
||||
SpriteBatch *newSpriteBatch(Texture *texture, int size, BufferDataUsage usage);
|
||||
@@ -819,12 +819,12 @@ public:
|
||||
/**
|
||||
* Converts PIXELFORMAT_NORMAL and PIXELFORMAT_HDR into a real format.
|
||||
**/
|
||||
virtual PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const = 0;
|
||||
PixelFormat getSizedFormat(PixelFormat format) const;
|
||||
|
||||
/**
|
||||
* Gets whether the specified pixel format usage is supported.
|
||||
**/
|
||||
virtual bool isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB = false) = 0;
|
||||
virtual bool isPixelFormatSupported(PixelFormat format, uint32 usage) = 0;
|
||||
|
||||
/**
|
||||
* Gets the renderer used by love.graphics.
|
||||
|
||||
@@ -81,6 +81,7 @@ GraphicsReadback::GraphicsReadback(Graphics *gfx, ReadbackMethod method, Texture
|
||||
}
|
||||
|
||||
textureFormat = getLinearPixelFormat(texture->getPixelFormat());
|
||||
isFormatLinear = isGammaCorrect() && !isPixelFormatSRGB(texture->getPixelFormat());
|
||||
|
||||
if (!image::ImageData::validPixelFormat(textureFormat))
|
||||
{
|
||||
@@ -96,7 +97,7 @@ GraphicsReadback::GraphicsReadback(Graphics *gfx, ReadbackMethod method, Texture
|
||||
if (isRT && !caps.features[Graphics::FEATURE_COPY_RENDER_TARGET_TO_BUFFER])
|
||||
throw love::Exception("readbackTextureAsync is not supported on this system.");
|
||||
else if (!isRT && !caps.features[Graphics::FEATURE_COPY_TEXTURE_TO_BUFFER])
|
||||
throw love::Exception("readbackTextureAsync a with non-render-target textures is not supported on this system.");
|
||||
throw love::Exception("readbackTextureAsync with a non-render-target texture is not supported on this system.");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -158,6 +159,7 @@ void *GraphicsReadback::prepareReadbackDest(size_t size)
|
||||
throw love::Exception("The love.image module must be loaded for readbackTexture.");
|
||||
|
||||
imageData.set(module->newImageData(rect.w, rect.h, textureFormat, nullptr), Acquire::NORETAIN);
|
||||
imageData->setLinear(isFormatLinear);
|
||||
return imageData->getData();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,6 +103,7 @@ protected:
|
||||
StrongRef<love::image::ImageData> imageData;
|
||||
Rect rect = {};
|
||||
PixelFormat textureFormat = PIXELFORMAT_UNKNOWN;
|
||||
bool isFormatLinear = false;
|
||||
int imageDataX = 0;
|
||||
int imageDataY = 0;
|
||||
|
||||
|
||||
@@ -1010,8 +1010,16 @@ bool Shader::validateInternal(StrongRef<ShaderStage> stages[], std::string &err,
|
||||
values[i].u = convertData<uint32>((*constarray)[i]);
|
||||
}
|
||||
break;
|
||||
case glslang::EbtInt:
|
||||
case glslang::EbtBool:
|
||||
u.dataType = DATA_BASETYPE_BOOL;
|
||||
if (constarray != nullptr)
|
||||
{
|
||||
values.resize(constarray->size());
|
||||
for (int i = 0; i < constarray->size(); i++)
|
||||
values[i].u = convertData<uint32>((*constarray)[i]);
|
||||
}
|
||||
break;
|
||||
case glslang::EbtInt:
|
||||
default:
|
||||
u.dataType = DATA_BASETYPE_INT;
|
||||
if (constarray != nullptr)
|
||||
|
||||
@@ -168,7 +168,6 @@ Texture::Texture(Graphics *gfx, const Settings &settings, const Slices *slices)
|
||||
, computeWrite(settings.computeWrite)
|
||||
, readable(true)
|
||||
, mipmapsMode(settings.mipmaps)
|
||||
, sRGB(isGammaCorrect() && !settings.linear)
|
||||
, width(settings.width)
|
||||
, height(settings.height)
|
||||
, depth(settings.type == TEXTURE_VOLUME ? settings.layers : 1)
|
||||
@@ -204,7 +203,7 @@ Texture::Texture(Graphics *gfx, const Settings &settings, const Slices *slices)
|
||||
love::image::ImageDataBase *slice = slices->get(0, 0);
|
||||
|
||||
format = slice->getFormat();
|
||||
if (sRGB)
|
||||
if (isGammaCorrect() && !slice->isLinear())
|
||||
format = getSRGBPixelFormat(format);
|
||||
|
||||
pixelWidth = slice->getWidth();
|
||||
@@ -235,7 +234,9 @@ Texture::Texture(Graphics *gfx, const Settings &settings, const Slices *slices)
|
||||
else
|
||||
readable = !renderTarget || !isPixelFormatDepthStencil(format);
|
||||
|
||||
format = gfx->getSizedFormat(format, renderTarget, readable);
|
||||
format = gfx->getSizedFormat(format);
|
||||
if (!isGammaCorrect() || settings.linear)
|
||||
format = getLinearPixelFormat(format);
|
||||
|
||||
if (mipmapsMode == MIPMAPS_AUTO && isCompressed())
|
||||
mipmapsMode = MIPMAPS_MANUAL;
|
||||
@@ -290,7 +291,7 @@ Texture::Texture(Graphics *gfx, const Settings &settings, const Slices *slices)
|
||||
if (computeWrite)
|
||||
usage |= PIXELFORMATUSAGEFLAGS_COMPUTEWRITE;
|
||||
|
||||
if (!gfx->isPixelFormatSupported(format, (PixelFormatUsageFlags) usage, sRGB))
|
||||
if (!gfx->isPixelFormatSupported(format, (PixelFormatUsageFlags) usage))
|
||||
{
|
||||
const char *fstr = "unknown";
|
||||
love::getConstant(format, fstr);
|
||||
@@ -621,7 +622,7 @@ bool Texture::isCompressed() const
|
||||
|
||||
bool Texture::isFormatLinear() const
|
||||
{
|
||||
return isGammaCorrect() && !sRGB && !isPixelFormatSRGB(format);
|
||||
return isGammaCorrect() && !isPixelFormatSRGB(format);
|
||||
}
|
||||
|
||||
bool Texture::isValidSlice(int slice, int mip) const
|
||||
@@ -885,6 +886,7 @@ bool Texture::Slices::validate() const
|
||||
int w = firstdata->getWidth();
|
||||
int h = firstdata->getHeight();
|
||||
PixelFormat format = firstdata->getFormat();
|
||||
bool linear = firstdata->isLinear();
|
||||
|
||||
if (textureType == TEXTURE_CUBE && w != h)
|
||||
throw love::Exception("Cube textures must have equal widths and heights for each cube face.");
|
||||
@@ -924,6 +926,9 @@ bool Texture::Slices::validate() const
|
||||
|
||||
if (format != slicedata->getFormat())
|
||||
throw love::Exception("All texture slices and mipmaps must have the same pixel format.");
|
||||
|
||||
if (linear != slicedata->isLinear())
|
||||
throw love::Exception("All texture slices and mipmaps must have the same linear setting.");
|
||||
}
|
||||
|
||||
mipw = std::max(mipw / 2, 1);
|
||||
|
||||
@@ -325,8 +325,6 @@ protected:
|
||||
|
||||
MipmapsMode mipmapsMode;
|
||||
|
||||
bool sRGB;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
|
||||
|
||||
@@ -110,8 +110,7 @@ public:
|
||||
|
||||
void setWireframe(bool enable) override;
|
||||
|
||||
PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const override;
|
||||
bool isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB = false) override;
|
||||
bool isPixelFormatSupported(PixelFormat format, uint32 usage) override;
|
||||
Renderer getRenderer() const override;
|
||||
bool usesGLSLES() const override;
|
||||
RendererInfo getRendererInfo() const override;
|
||||
|
||||
@@ -503,7 +503,7 @@ void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelh
|
||||
backbufferMSAA.set(nullptr);
|
||||
if (settings.msaa > 1)
|
||||
{
|
||||
settings.format = isGammaCorrect() ? PIXELFORMAT_BGRA8_UNORM_sRGB : PIXELFORMAT_BGRA8_UNORM;
|
||||
settings.format = isGammaCorrect() ? PIXELFORMAT_BGRA8_sRGB : PIXELFORMAT_BGRA8_UNORM;
|
||||
backbufferMSAA.set(newTexture(settings), Acquire::NORETAIN);
|
||||
}
|
||||
|
||||
@@ -681,7 +681,7 @@ id<MTLRenderCommandEncoder> Graphics::useRenderEncoder()
|
||||
attachmentStoreActions.stencil = MTLStoreActionDontCare;
|
||||
|
||||
auto &key = lastRenderPipelineKey;
|
||||
key.colorRenderTargetFormats = isGammaCorrect() ? PIXELFORMAT_BGRA8_UNORM_sRGB : PIXELFORMAT_BGRA8_UNORM;
|
||||
key.colorRenderTargetFormats = isGammaCorrect() ? PIXELFORMAT_BGRA8_sRGB : PIXELFORMAT_BGRA8_UNORM;
|
||||
key.depthStencilFormat = backbufferDepthStencil->getPixelFormat();
|
||||
key.msaa = backbufferMSAA ? (uint8) backbufferMSAA->getMSAA() : 1;
|
||||
}
|
||||
@@ -1864,31 +1864,9 @@ void Graphics::setWireframe(bool enable)
|
||||
}
|
||||
}
|
||||
|
||||
PixelFormat Graphics::getSizedFormat(PixelFormat format, bool /*rendertarget*/, bool /*readable*/) const
|
||||
bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case PIXELFORMAT_NORMAL:
|
||||
if (isGammaCorrect())
|
||||
return PIXELFORMAT_RGBA8_UNORM_sRGB;
|
||||
else
|
||||
return PIXELFORMAT_RGBA8_UNORM;
|
||||
case PIXELFORMAT_HDR:
|
||||
return PIXELFORMAT_RGBA16_FLOAT;
|
||||
default:
|
||||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB)
|
||||
{
|
||||
bool rendertarget = (usage & PIXELFORMATUSAGEFLAGS_RENDERTARGET) != 0;
|
||||
bool readable = (usage & PIXELFORMATUSAGEFLAGS_SAMPLE) != 0;
|
||||
|
||||
format = getSizedFormat(format, rendertarget, readable);
|
||||
|
||||
if (sRGB)
|
||||
format = getSRGBPixelFormat(format);
|
||||
format = getSizedFormat(format);
|
||||
|
||||
const uint32 sample = PIXELFORMATUSAGEFLAGS_SAMPLE;
|
||||
const uint32 filter = PIXELFORMATUSAGEFLAGS_LINEAR;
|
||||
@@ -1902,7 +1880,7 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRG
|
||||
|
||||
uint32 flags = PIXELFORMATUSAGEFLAGS_NONE;
|
||||
|
||||
if (isPixelFormatCompressed(format) && rendertarget)
|
||||
if (isPixelFormatCompressed(format) && (usage & rt) != 0)
|
||||
return false;
|
||||
|
||||
// https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
|
||||
@@ -1977,8 +1955,8 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRG
|
||||
case PIXELFORMAT_BGRA8_UNORM:
|
||||
flags |= all;
|
||||
break;
|
||||
case PIXELFORMAT_RGBA8_UNORM_sRGB:
|
||||
case PIXELFORMAT_BGRA8_UNORM_sRGB:
|
||||
case PIXELFORMAT_RGBA8_sRGB:
|
||||
case PIXELFORMAT_BGRA8_sRGB:
|
||||
if (families.apple[1] || families.mac[1] || families.macCatalyst[1])
|
||||
flags |= commonsample | commonrender;
|
||||
if (families.apple[2])
|
||||
@@ -2077,8 +2055,11 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRG
|
||||
break;
|
||||
|
||||
case PIXELFORMAT_DXT1_UNORM:
|
||||
case PIXELFORMAT_DXT1_sRGB:
|
||||
case PIXELFORMAT_DXT3_UNORM:
|
||||
case PIXELFORMAT_DXT3_sRGB:
|
||||
case PIXELFORMAT_DXT5_UNORM:
|
||||
case PIXELFORMAT_DXT5_sRGB:
|
||||
case PIXELFORMAT_BC4_UNORM:
|
||||
case PIXELFORMAT_BC4_SNORM:
|
||||
case PIXELFORMAT_BC5_UNORM:
|
||||
@@ -2086,22 +2067,30 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRG
|
||||
case PIXELFORMAT_BC6H_UFLOAT:
|
||||
case PIXELFORMAT_BC6H_FLOAT:
|
||||
case PIXELFORMAT_BC7_UNORM:
|
||||
case PIXELFORMAT_BC7_sRGB:
|
||||
if (families.mac[1] || families.macCatalyst[1])
|
||||
flags |= commonsample;
|
||||
break;
|
||||
|
||||
case PIXELFORMAT_PVR1_RGB2_UNORM:
|
||||
case PIXELFORMAT_PVR1_RGB2_sRGB:
|
||||
case PIXELFORMAT_PVR1_RGB4_UNORM:
|
||||
case PIXELFORMAT_PVR1_RGB4_sRGB:
|
||||
case PIXELFORMAT_PVR1_RGBA2_UNORM:
|
||||
case PIXELFORMAT_PVR1_RGBA2_sRGB:
|
||||
case PIXELFORMAT_PVR1_RGBA4_UNORM:
|
||||
case PIXELFORMAT_PVR1_RGBA4_sRGB:
|
||||
if (families.apple[1])
|
||||
flags |= commonsample;
|
||||
break;
|
||||
|
||||
case PIXELFORMAT_ETC1_UNORM:
|
||||
case PIXELFORMAT_ETC2_RGB_UNORM:
|
||||
case PIXELFORMAT_ETC2_RGB_sRGB:
|
||||
case PIXELFORMAT_ETC2_RGBA_UNORM:
|
||||
case PIXELFORMAT_ETC2_RGBA_sRGB:
|
||||
case PIXELFORMAT_ETC2_RGBA1_UNORM:
|
||||
case PIXELFORMAT_ETC2_RGBA1_sRGB:
|
||||
case PIXELFORMAT_EAC_R_UNORM:
|
||||
case PIXELFORMAT_EAC_R_SNORM:
|
||||
case PIXELFORMAT_EAC_RG_UNORM:
|
||||
@@ -2110,20 +2099,34 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRG
|
||||
flags |= commonsample;
|
||||
break;
|
||||
|
||||
case PIXELFORMAT_ASTC_4x4:
|
||||
case PIXELFORMAT_ASTC_5x4:
|
||||
case PIXELFORMAT_ASTC_5x5:
|
||||
case PIXELFORMAT_ASTC_6x5:
|
||||
case PIXELFORMAT_ASTC_6x6:
|
||||
case PIXELFORMAT_ASTC_8x5:
|
||||
case PIXELFORMAT_ASTC_8x6:
|
||||
case PIXELFORMAT_ASTC_8x8:
|
||||
case PIXELFORMAT_ASTC_10x5:
|
||||
case PIXELFORMAT_ASTC_10x6:
|
||||
case PIXELFORMAT_ASTC_10x8:
|
||||
case PIXELFORMAT_ASTC_10x10:
|
||||
case PIXELFORMAT_ASTC_12x10:
|
||||
case PIXELFORMAT_ASTC_12x12:
|
||||
case PIXELFORMAT_ASTC_4x4_UNORM:
|
||||
case PIXELFORMAT_ASTC_5x4_UNORM:
|
||||
case PIXELFORMAT_ASTC_5x5_UNORM:
|
||||
case PIXELFORMAT_ASTC_6x5_UNORM:
|
||||
case PIXELFORMAT_ASTC_6x6_UNORM:
|
||||
case PIXELFORMAT_ASTC_8x5_UNORM:
|
||||
case PIXELFORMAT_ASTC_8x6_UNORM:
|
||||
case PIXELFORMAT_ASTC_8x8_UNORM:
|
||||
case PIXELFORMAT_ASTC_10x5_UNORM:
|
||||
case PIXELFORMAT_ASTC_10x6_UNORM:
|
||||
case PIXELFORMAT_ASTC_10x8_UNORM:
|
||||
case PIXELFORMAT_ASTC_10x10_UNORM:
|
||||
case PIXELFORMAT_ASTC_12x10_UNORM:
|
||||
case PIXELFORMAT_ASTC_12x12_UNORM:
|
||||
case PIXELFORMAT_ASTC_4x4_sRGB:
|
||||
case PIXELFORMAT_ASTC_5x4_sRGB:
|
||||
case PIXELFORMAT_ASTC_5x5_sRGB:
|
||||
case PIXELFORMAT_ASTC_6x5_sRGB:
|
||||
case PIXELFORMAT_ASTC_6x6_sRGB:
|
||||
case PIXELFORMAT_ASTC_8x5_sRGB:
|
||||
case PIXELFORMAT_ASTC_8x6_sRGB:
|
||||
case PIXELFORMAT_ASTC_8x8_sRGB:
|
||||
case PIXELFORMAT_ASTC_10x5_sRGB:
|
||||
case PIXELFORMAT_ASTC_10x6_sRGB:
|
||||
case PIXELFORMAT_ASTC_10x8_sRGB:
|
||||
case PIXELFORMAT_ASTC_10x10_sRGB:
|
||||
case PIXELFORMAT_ASTC_12x10_sRGB:
|
||||
case PIXELFORMAT_ASTC_12x12_sRGB:
|
||||
if (families.apple[2])
|
||||
flags |= commonsample;
|
||||
break;
|
||||
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
API_AVAILABLE(macos(10.15), ios(13.0)) MTLTextureSwizzleChannels swizzle;
|
||||
};
|
||||
|
||||
static PixelFormatDesc convertPixelFormat(id<MTLDevice> device, PixelFormat format, bool &isSRGB);
|
||||
static PixelFormatDesc convertPixelFormat(id<MTLDevice> device, PixelFormat format);
|
||||
|
||||
}; // Metal
|
||||
|
||||
|
||||
@@ -28,17 +28,11 @@ namespace graphics
|
||||
namespace metal
|
||||
{
|
||||
|
||||
Metal::PixelFormatDesc Metal::convertPixelFormat(id<MTLDevice> device, PixelFormat format, bool &isSRGB)
|
||||
Metal::PixelFormatDesc Metal::convertPixelFormat(id<MTLDevice> device, PixelFormat format)
|
||||
{
|
||||
MTLPixelFormat mtlformat = MTLPixelFormatInvalid;
|
||||
PixelFormatDesc desc = {};
|
||||
|
||||
if (isSRGB)
|
||||
format = getSRGBPixelFormat(format);
|
||||
|
||||
if (!isPixelFormatCompressed(format) && !isPixelFormatSRGB(format))
|
||||
isSRGB = false;
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case PIXELFORMAT_R8_UNORM:
|
||||
@@ -50,13 +44,13 @@ Metal::PixelFormatDesc Metal::convertPixelFormat(id<MTLDevice> device, PixelForm
|
||||
case PIXELFORMAT_RGBA8_UNORM:
|
||||
mtlformat = MTLPixelFormatRGBA8Unorm;
|
||||
break;
|
||||
case PIXELFORMAT_RGBA8_UNORM_sRGB:
|
||||
case PIXELFORMAT_RGBA8_sRGB:
|
||||
mtlformat = MTLPixelFormatRGBA8Unorm_sRGB;
|
||||
break;
|
||||
case PIXELFORMAT_BGRA8_UNORM:
|
||||
mtlformat = MTLPixelFormatBGRA8Unorm;
|
||||
break;
|
||||
case PIXELFORMAT_BGRA8_UNORM_sRGB:
|
||||
case PIXELFORMAT_BGRA8_sRGB:
|
||||
mtlformat = MTLPixelFormatBGRA8Unorm_sRGB;
|
||||
break;
|
||||
case PIXELFORMAT_R16_UNORM:
|
||||
@@ -205,177 +199,264 @@ Metal::PixelFormatDesc Metal::convertPixelFormat(id<MTLDevice> device, PixelForm
|
||||
|
||||
case PIXELFORMAT_DXT1_UNORM:
|
||||
#ifndef LOVE_IOS
|
||||
mtlformat = isSRGB ? MTLPixelFormatBC1_RGBA_sRGB : MTLPixelFormatBC1_RGBA;
|
||||
mtlformat = MTLPixelFormatBC1_RGBA;
|
||||
#endif
|
||||
break;
|
||||
case PIXELFORMAT_DXT1_sRGB:
|
||||
#ifndef LOVE_IOS
|
||||
mtlformat = MTLPixelFormatBC1_RGBA_sRGB;
|
||||
#endif
|
||||
break;
|
||||
case PIXELFORMAT_DXT3_UNORM:
|
||||
#ifndef LOVE_IOS
|
||||
mtlformat = isSRGB ? MTLPixelFormatBC2_RGBA_sRGB : MTLPixelFormatBC2_RGBA;
|
||||
mtlformat = MTLPixelFormatBC2_RGBA;
|
||||
#endif
|
||||
break;
|
||||
case PIXELFORMAT_DXT3_sRGB:
|
||||
#ifndef LOVE_IOS
|
||||
mtlformat = MTLPixelFormatBC2_RGBA_sRGB;
|
||||
#endif
|
||||
break;
|
||||
case PIXELFORMAT_DXT5_UNORM:
|
||||
#ifndef LOVE_IOS
|
||||
mtlformat = isSRGB ? MTLPixelFormatBC3_RGBA_sRGB : MTLPixelFormatBC3_RGBA;
|
||||
mtlformat = MTLPixelFormatBC3_RGBA;
|
||||
#endif
|
||||
break;
|
||||
case PIXELFORMAT_DXT5_sRGB:
|
||||
#ifndef LOVE_IOS
|
||||
mtlformat = MTLPixelFormatBC3_RGBA_sRGB;
|
||||
#endif
|
||||
break;
|
||||
case PIXELFORMAT_BC4_UNORM:
|
||||
#ifndef LOVE_IOS
|
||||
isSRGB = false;
|
||||
mtlformat = MTLPixelFormatBC4_RUnorm;
|
||||
#endif
|
||||
break;
|
||||
case PIXELFORMAT_BC4_SNORM:
|
||||
#ifndef LOVE_IOS
|
||||
isSRGB = false;
|
||||
mtlformat = MTLPixelFormatBC4_RSnorm;
|
||||
#endif
|
||||
break;
|
||||
case PIXELFORMAT_BC5_UNORM:
|
||||
#ifndef LOVE_IOS
|
||||
isSRGB = false;
|
||||
mtlformat = MTLPixelFormatBC5_RGUnorm;
|
||||
#endif
|
||||
break;
|
||||
case PIXELFORMAT_BC5_SNORM:
|
||||
#ifndef LOVE_IOS
|
||||
isSRGB = false;
|
||||
mtlformat = MTLPixelFormatBC5_RGSnorm;
|
||||
#endif
|
||||
break;
|
||||
case PIXELFORMAT_BC6H_UFLOAT:
|
||||
#ifndef LOVE_IOS
|
||||
isSRGB = false;
|
||||
mtlformat = MTLPixelFormatBC6H_RGBUfloat;
|
||||
#endif
|
||||
break;
|
||||
case PIXELFORMAT_BC6H_FLOAT:
|
||||
#ifndef LOVE_IOS
|
||||
isSRGB = false;
|
||||
mtlformat = MTLPixelFormatBC6H_RGBFloat;
|
||||
#endif
|
||||
break;
|
||||
case PIXELFORMAT_BC7_UNORM:
|
||||
#ifndef LOVE_IOS
|
||||
mtlformat = isSRGB ? MTLPixelFormatBC7_RGBAUnorm_sRGB : MTLPixelFormatBC7_RGBAUnorm;
|
||||
mtlformat = MTLPixelFormatBC7_RGBAUnorm;
|
||||
#endif
|
||||
break;
|
||||
case PIXELFORMAT_BC7_sRGB:
|
||||
#ifndef LOVE_IOS
|
||||
mtlformat = MTLPixelFormatBC7_RGBAUnorm_sRGB;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case PIXELFORMAT_PVR1_RGB2_UNORM:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = isSRGB ? MTLPixelFormatPVRTC_RGB_2BPP_sRGB : MTLPixelFormatPVRTC_RGB_2BPP;
|
||||
mtlformat = MTLPixelFormatPVRTC_RGB_2BPP;
|
||||
break;
|
||||
case PIXELFORMAT_PVR1_RGB2_sRGB:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = MTLPixelFormatPVRTC_RGB_2BPP_sRGB;
|
||||
break;
|
||||
case PIXELFORMAT_PVR1_RGB4_UNORM:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = isSRGB ? MTLPixelFormatPVRTC_RGB_4BPP_sRGB : MTLPixelFormatPVRTC_RGB_4BPP;
|
||||
mtlformat = MTLPixelFormatPVRTC_RGB_4BPP;
|
||||
break;
|
||||
case PIXELFORMAT_PVR1_RGB4_sRGB:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = MTLPixelFormatPVRTC_RGB_4BPP_sRGB;
|
||||
break;
|
||||
case PIXELFORMAT_PVR1_RGBA2_UNORM:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = isSRGB ? MTLPixelFormatPVRTC_RGB_2BPP_sRGB : MTLPixelFormatPVRTC_RGBA_2BPP;
|
||||
mtlformat = MTLPixelFormatPVRTC_RGBA_2BPP;
|
||||
break;
|
||||
case PIXELFORMAT_PVR1_RGBA2_sRGB:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = MTLPixelFormatPVRTC_RGB_2BPP_sRGB;
|
||||
break;
|
||||
case PIXELFORMAT_PVR1_RGBA4_UNORM:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = isSRGB ? MTLPixelFormatPVRTC_RGB_4BPP_sRGB : MTLPixelFormatPVRTC_RGBA_4BPP;
|
||||
mtlformat = MTLPixelFormatPVRTC_RGBA_4BPP;
|
||||
break;
|
||||
case PIXELFORMAT_PVR1_RGBA4_sRGB:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = MTLPixelFormatPVRTC_RGB_4BPP_sRGB;
|
||||
break;
|
||||
|
||||
case PIXELFORMAT_ETC1_UNORM:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = isSRGB ? MTLPixelFormatETC2_RGB8_sRGB : MTLPixelFormatETC2_RGB8;
|
||||
mtlformat = MTLPixelFormatETC2_RGB8;
|
||||
break;
|
||||
case PIXELFORMAT_ETC2_RGB_UNORM:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = isSRGB ? MTLPixelFormatETC2_RGB8_sRGB : MTLPixelFormatETC2_RGB8;
|
||||
mtlformat = MTLPixelFormatETC2_RGB8;
|
||||
break;
|
||||
case PIXELFORMAT_ETC2_RGB_sRGB:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = MTLPixelFormatETC2_RGB8_sRGB;
|
||||
break;
|
||||
case PIXELFORMAT_ETC2_RGBA_UNORM:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = isSRGB ? MTLPixelFormatEAC_RGBA8_sRGB : MTLPixelFormatEAC_RGBA8;
|
||||
mtlformat = MTLPixelFormatEAC_RGBA8;
|
||||
break;
|
||||
case PIXELFORMAT_ETC2_RGBA_sRGB:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = MTLPixelFormatEAC_RGBA8_sRGB;
|
||||
break;
|
||||
case PIXELFORMAT_ETC2_RGBA1_UNORM:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = isSRGB ? MTLPixelFormatETC2_RGB8A1_sRGB : MTLPixelFormatETC2_RGB8A1;
|
||||
mtlformat = MTLPixelFormatETC2_RGB8A1;
|
||||
break;
|
||||
case PIXELFORMAT_ETC2_RGBA1_sRGB:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = MTLPixelFormatETC2_RGB8A1_sRGB;
|
||||
break;
|
||||
case PIXELFORMAT_EAC_R_UNORM:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
{
|
||||
isSRGB = false;
|
||||
mtlformat = MTLPixelFormatEAC_R11Unorm;
|
||||
}
|
||||
break;
|
||||
case PIXELFORMAT_EAC_R_SNORM:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
{
|
||||
isSRGB = false;
|
||||
mtlformat = MTLPixelFormatEAC_R11Snorm;
|
||||
}
|
||||
break;
|
||||
case PIXELFORMAT_EAC_RG_UNORM:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
{
|
||||
isSRGB = false;
|
||||
mtlformat = MTLPixelFormatEAC_RG11Unorm;
|
||||
}
|
||||
break;
|
||||
case PIXELFORMAT_EAC_RG_SNORM:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
{
|
||||
isSRGB = false;
|
||||
mtlformat = MTLPixelFormatEAC_RG11Snorm;
|
||||
}
|
||||
break;
|
||||
|
||||
case PIXELFORMAT_ASTC_4x4:
|
||||
case PIXELFORMAT_ASTC_4x4_UNORM:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = isSRGB ? MTLPixelFormatASTC_4x4_sRGB : MTLPixelFormatASTC_4x4_LDR;
|
||||
mtlformat = MTLPixelFormatASTC_4x4_LDR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_5x4:
|
||||
case PIXELFORMAT_ASTC_5x4_UNORM:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = isSRGB ? MTLPixelFormatASTC_5x4_sRGB : MTLPixelFormatASTC_5x4_LDR;
|
||||
mtlformat = MTLPixelFormatASTC_5x4_LDR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_5x5:
|
||||
case PIXELFORMAT_ASTC_5x5_UNORM:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = isSRGB ? MTLPixelFormatASTC_5x5_sRGB : MTLPixelFormatASTC_5x5_LDR;
|
||||
mtlformat = MTLPixelFormatASTC_5x5_LDR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_6x5:
|
||||
case PIXELFORMAT_ASTC_6x5_UNORM:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = isSRGB ? MTLPixelFormatASTC_6x5_sRGB : MTLPixelFormatASTC_6x5_LDR;
|
||||
mtlformat = MTLPixelFormatASTC_6x5_LDR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_6x6:
|
||||
case PIXELFORMAT_ASTC_6x6_UNORM:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = isSRGB ? MTLPixelFormatASTC_6x6_sRGB : MTLPixelFormatASTC_6x6_LDR;
|
||||
mtlformat = MTLPixelFormatASTC_6x6_LDR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_8x5:
|
||||
case PIXELFORMAT_ASTC_8x5_UNORM:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = isSRGB ? MTLPixelFormatASTC_8x5_sRGB : MTLPixelFormatASTC_8x5_LDR;
|
||||
mtlformat = MTLPixelFormatASTC_8x5_LDR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_8x6:
|
||||
case PIXELFORMAT_ASTC_8x6_UNORM:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = isSRGB ? MTLPixelFormatASTC_8x6_sRGB : MTLPixelFormatASTC_8x6_LDR;
|
||||
mtlformat = MTLPixelFormatASTC_8x6_LDR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_8x8:
|
||||
case PIXELFORMAT_ASTC_8x8_UNORM:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = isSRGB ? MTLPixelFormatASTC_8x8_sRGB : MTLPixelFormatASTC_8x8_LDR;
|
||||
mtlformat = MTLPixelFormatASTC_8x8_LDR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x5:
|
||||
case PIXELFORMAT_ASTC_10x5_UNORM:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = isSRGB ? MTLPixelFormatASTC_10x5_sRGB : MTLPixelFormatASTC_10x5_LDR;
|
||||
mtlformat = MTLPixelFormatASTC_10x5_LDR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x6:
|
||||
case PIXELFORMAT_ASTC_10x6_UNORM:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = isSRGB ? MTLPixelFormatASTC_10x6_sRGB : MTLPixelFormatASTC_10x6_LDR;
|
||||
mtlformat = MTLPixelFormatASTC_10x6_LDR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x8:
|
||||
case PIXELFORMAT_ASTC_10x8_UNORM:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = isSRGB ? MTLPixelFormatASTC_10x8_sRGB : MTLPixelFormatASTC_10x8_LDR;
|
||||
mtlformat = MTLPixelFormatASTC_10x8_LDR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x10:
|
||||
case PIXELFORMAT_ASTC_10x10_UNORM:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = isSRGB ? MTLPixelFormatASTC_10x10_sRGB : MTLPixelFormatASTC_10x10_LDR;
|
||||
mtlformat = MTLPixelFormatASTC_10x10_LDR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_12x10:
|
||||
case PIXELFORMAT_ASTC_12x10_UNORM:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = isSRGB ? MTLPixelFormatASTC_12x10_sRGB : MTLPixelFormatASTC_12x10_LDR;
|
||||
mtlformat = MTLPixelFormatASTC_12x10_LDR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_12x12:
|
||||
case PIXELFORMAT_ASTC_12x12_UNORM:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = isSRGB ? MTLPixelFormatASTC_12x12_sRGB : MTLPixelFormatASTC_12x12_LDR;
|
||||
mtlformat = MTLPixelFormatASTC_12x12_LDR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_4x4_sRGB:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = MTLPixelFormatASTC_4x4_sRGB;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_5x4_sRGB:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = MTLPixelFormatASTC_5x4_sRGB;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_5x5_sRGB:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = MTLPixelFormatASTC_5x5_sRGB;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_6x5_sRGB:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = MTLPixelFormatASTC_6x5_sRGB;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_6x6_sRGB:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = MTLPixelFormatASTC_6x6_sRGB;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_8x5_sRGB:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = MTLPixelFormatASTC_8x5_sRGB;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_8x6_sRGB:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = MTLPixelFormatASTC_8x6_sRGB;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_8x8_sRGB:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = MTLPixelFormatASTC_8x8_sRGB;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x5_sRGB:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = MTLPixelFormatASTC_10x5_sRGB;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x6_sRGB:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = MTLPixelFormatASTC_10x6_sRGB;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x8_sRGB:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = MTLPixelFormatASTC_10x8_sRGB;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x10_sRGB:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = MTLPixelFormatASTC_10x10_sRGB;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_12x10_sRGB:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = MTLPixelFormatASTC_12x10_sRGB;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_12x12_sRGB:
|
||||
if (@available(macOS 11.0, iOS 8.0, *))
|
||||
mtlformat = MTLPixelFormatASTC_12x12_sRGB;
|
||||
break;
|
||||
|
||||
case PIXELFORMAT_UNKNOWN:
|
||||
|
||||
@@ -1087,8 +1087,7 @@ id<MTLRenderPipelineState> Shader::getCachedRenderPipeline(const RenderPipelineK
|
||||
|
||||
MTLRenderPipelineColorAttachmentDescriptor *attachment = desc.colorAttachments[i];
|
||||
|
||||
bool isSRGB = false;
|
||||
auto formatdesc = Metal::convertPixelFormat(device, format, isSRGB);
|
||||
auto formatdesc = Metal::convertPixelFormat(device, format);
|
||||
attachment.pixelFormat = formatdesc.format;
|
||||
|
||||
if (key.blend.enable)
|
||||
@@ -1124,8 +1123,7 @@ id<MTLRenderPipelineState> Shader::getCachedRenderPipeline(const RenderPipelineK
|
||||
{
|
||||
// We already don't really support metal on older systems, this just
|
||||
// silences a compiler warning about it.
|
||||
bool isSRGB = false;
|
||||
auto formatdesc = Metal::convertPixelFormat(device, dsformat, isSRGB);
|
||||
auto formatdesc = Metal::convertPixelFormat(device, dsformat);
|
||||
if (isPixelFormatDepth(dsformat))
|
||||
desc.depthAttachmentPixelFormat = formatdesc.format;
|
||||
if (isPixelFormatStencil(dsformat))
|
||||
|
||||
@@ -62,7 +62,7 @@ Texture::Texture(love::graphics::Graphics *gfxbase, id<MTLDevice> device, const
|
||||
desc.mipmapLevelCount = mipmapCount;
|
||||
desc.textureType = getMTLTextureType(texType, 1);
|
||||
|
||||
auto formatdesc = Metal::convertPixelFormat(device, format, sRGB);
|
||||
auto formatdesc = Metal::convertPixelFormat(device, format);
|
||||
desc.pixelFormat = formatdesc.format;
|
||||
if (formatdesc.swizzled)
|
||||
{
|
||||
|
||||
@@ -250,7 +250,7 @@ void Graphics::updateBackbuffer(int width, int height, int /*pixelwidth*/, int p
|
||||
settings.renderTarget = true;
|
||||
settings.readable.set(false);
|
||||
|
||||
settings.format = isGammaCorrect() ? PIXELFORMAT_RGBA8_UNORM_sRGB : PIXELFORMAT_RGBA8_UNORM;
|
||||
settings.format = isGammaCorrect() ? PIXELFORMAT_RGBA8_sRGB : PIXELFORMAT_RGBA8_UNORM;
|
||||
internalBackbuffer.set(newTexture(settings), Acquire::NORETAIN);
|
||||
|
||||
settings.format = PIXELFORMAT_DEPTH24_UNORM_STENCIL8;
|
||||
@@ -909,6 +909,30 @@ void Graphics::endPass(bool presenting)
|
||||
|
||||
void Graphics::clear(OptionalColorD c, OptionalInt stencil, OptionalDouble depth)
|
||||
{
|
||||
if (c.hasValue)
|
||||
{
|
||||
bool hasintegerformat = false;
|
||||
|
||||
const auto &rts = states.back().renderTargets;
|
||||
for (const auto &rt : rts.colors)
|
||||
{
|
||||
if (rt.texture.get() && isPixelFormatInteger(rt.texture->getPixelFormat()))
|
||||
hasintegerformat = true;
|
||||
}
|
||||
|
||||
// This variant of clear() uses glClear() which can't clear integer formats,
|
||||
// so we switch to the MRT variant if needed.
|
||||
if (hasintegerformat)
|
||||
{
|
||||
std::vector<OptionalColorD> colors(rts.colors.size());
|
||||
for (size_t i = 0; i < colors.size(); i++)
|
||||
colors[i] = c;
|
||||
|
||||
clear(colors, stencil, depth);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (c.hasValue || stencil.hasValue || depth.hasValue)
|
||||
flushBatchedDraws();
|
||||
|
||||
@@ -922,36 +946,23 @@ void Graphics::clear(OptionalColorD c, OptionalInt stencil, OptionalDouble depth
|
||||
flags |= GL_COLOR_BUFFER_BIT;
|
||||
}
|
||||
|
||||
uint32 stencilwrites = gl.getStencilWriteMask();
|
||||
|
||||
if (stencil.hasValue)
|
||||
{
|
||||
if (stencilwrites != LOVE_UINT32_MAX)
|
||||
gl.setStencilWriteMask(LOVE_UINT32_MAX);
|
||||
|
||||
glClearStencil(stencil.value);
|
||||
flags |= GL_STENCIL_BUFFER_BIT;
|
||||
}
|
||||
|
||||
bool hadDepthWrites = gl.hasDepthWrites();
|
||||
|
||||
if (depth.hasValue)
|
||||
{
|
||||
if (!hadDepthWrites) // glDepthMask also affects glClear.
|
||||
gl.setDepthWrites(true);
|
||||
|
||||
gl.clearDepth(depth.value);
|
||||
flags |= GL_DEPTH_BUFFER_BIT;
|
||||
}
|
||||
|
||||
if (flags != 0)
|
||||
{
|
||||
OpenGL::CleanClearState cs(flags);
|
||||
glClear(flags);
|
||||
|
||||
if (stencil.hasValue && stencilwrites != LOVE_UINT32_MAX)
|
||||
gl.setStencilWriteMask(stencilwrites);
|
||||
|
||||
if (depth.hasValue && !hadDepthWrites)
|
||||
gl.setDepthWrites(hadDepthWrites);
|
||||
}
|
||||
|
||||
if (c.hasValue && gl.bugs.clearRequiresDriverTextureStateUpdate && Shader::current)
|
||||
{
|
||||
@@ -1041,36 +1052,23 @@ void Graphics::clear(const std::vector<OptionalColorD> &colors, OptionalInt sten
|
||||
|
||||
GLbitfield flags = 0;
|
||||
|
||||
uint32 stencilwrites = gl.getStencilWriteMask();
|
||||
|
||||
if (stencil.hasValue)
|
||||
{
|
||||
if (stencilwrites != LOVE_UINT32_MAX)
|
||||
gl.setStencilWriteMask(LOVE_UINT32_MAX);
|
||||
|
||||
glClearStencil(stencil.value);
|
||||
flags |= GL_STENCIL_BUFFER_BIT;
|
||||
}
|
||||
|
||||
bool hadDepthWrites = gl.hasDepthWrites();
|
||||
|
||||
if (depth.hasValue)
|
||||
{
|
||||
if (!hadDepthWrites) // glDepthMask also affects glClear.
|
||||
gl.setDepthWrites(true);
|
||||
|
||||
gl.clearDepth(depth.value);
|
||||
flags |= GL_DEPTH_BUFFER_BIT;
|
||||
}
|
||||
|
||||
if (flags != 0)
|
||||
{
|
||||
OpenGL::CleanClearState cs(flags);
|
||||
glClear(flags);
|
||||
|
||||
if (stencil.hasValue && stencilwrites != LOVE_UINT32_MAX)
|
||||
gl.setStencilWriteMask(stencilwrites);
|
||||
|
||||
if (depth.hasValue && !hadDepthWrites)
|
||||
gl.setDepthWrites(hadDepthWrites);
|
||||
}
|
||||
|
||||
if (gl.bugs.clearRequiresDriverTextureStateUpdate && Shader::current)
|
||||
{
|
||||
@@ -1191,8 +1189,7 @@ GLuint Graphics::bindCachedFBO(const RenderTargets &targets)
|
||||
auto attachRT = [&](const RenderTarget &rt)
|
||||
{
|
||||
bool renderbuffer = msaa > 1 || !rt.texture->isReadable();
|
||||
bool srgb = false;
|
||||
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(rt.texture->getPixelFormat(), renderbuffer, srgb);
|
||||
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(rt.texture->getPixelFormat(), renderbuffer);
|
||||
|
||||
if (fmt.framebufferAttachments[0] == GL_COLOR_ATTACHMENT0)
|
||||
{
|
||||
@@ -1568,7 +1565,11 @@ void Graphics::setColorMask(ColorChannelMask mask)
|
||||
{
|
||||
flushBatchedDraws();
|
||||
|
||||
glColorMask(mask.r, mask.g, mask.b, mask.a);
|
||||
uint32 maskbits =
|
||||
((mask.r ? 1 : 0) << 0) | ((mask.g ? 1 : 0) << 1) |
|
||||
((mask.b ? 1 : 0) << 2) | ((mask.a ? 1 : 0) << 3);
|
||||
|
||||
gl.setColorWriteMask(maskbits);
|
||||
states.back().colorMask = mask;
|
||||
}
|
||||
|
||||
@@ -1732,31 +1733,6 @@ void Graphics::initCapabilities()
|
||||
}
|
||||
}
|
||||
|
||||
PixelFormat Graphics::getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const
|
||||
{
|
||||
uint32 requiredflags = 0;
|
||||
if (rendertarget)
|
||||
requiredflags |= PIXELFORMATUSAGEFLAGS_RENDERTARGET;
|
||||
if (readable)
|
||||
requiredflags |= PIXELFORMATUSAGEFLAGS_SAMPLE;
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case PIXELFORMAT_NORMAL:
|
||||
if (isGammaCorrect())
|
||||
return PIXELFORMAT_RGBA8_UNORM_sRGB;
|
||||
else if ((OpenGL::getPixelFormatUsageFlags(PIXELFORMAT_RGBA8_UNORM) & requiredflags) != requiredflags)
|
||||
// 32-bit render targets don't have guaranteed support on GLES2.
|
||||
return PIXELFORMAT_RGBA4_UNORM;
|
||||
else
|
||||
return PIXELFORMAT_RGBA8_UNORM;
|
||||
case PIXELFORMAT_HDR:
|
||||
return PIXELFORMAT_RGBA16_FLOAT;
|
||||
default:
|
||||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 Graphics::computePixelFormatUsage(PixelFormat format, bool readable)
|
||||
{
|
||||
uint32 usage = OpenGL::getPixelFormatUsageFlags(format);
|
||||
@@ -1777,9 +1753,8 @@ uint32 Graphics::computePixelFormatUsage(PixelFormat format, bool readable)
|
||||
{
|
||||
GLuint texture = 0;
|
||||
GLuint renderbuffer = 0;
|
||||
bool sRGB = isPixelFormatSRGB(format);
|
||||
|
||||
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(format, !readable, sRGB);
|
||||
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(format, !readable);
|
||||
|
||||
GLuint current_fbo = gl.getFramebuffer(OpenGL::FRAMEBUFFER_ALL);
|
||||
|
||||
@@ -1801,7 +1776,7 @@ uint32 Graphics::computePixelFormatUsage(PixelFormat format, bool readable)
|
||||
s.minFilter = s.magFilter = SamplerState::FILTER_NEAREST;
|
||||
gl.setSamplerState(TEXTURE_2D, s);
|
||||
|
||||
gl.rawTexStorage(TEXTURE_2D, 1, format, sRGB, 1, 1);
|
||||
gl.rawTexStorage(TEXTURE_2D, 1, format, 1, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1837,16 +1812,11 @@ uint32 Graphics::computePixelFormatUsage(PixelFormat format, bool readable)
|
||||
return usage;
|
||||
}
|
||||
|
||||
bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB)
|
||||
bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage)
|
||||
{
|
||||
if (sRGB)
|
||||
format = getSRGBPixelFormat(format);
|
||||
format = getSizedFormat(format);
|
||||
|
||||
bool rendertarget = (usage & PIXELFORMATUSAGEFLAGS_RENDERTARGET) != 0;
|
||||
bool readable = (usage & PIXELFORMATUSAGEFLAGS_SAMPLE) != 0;
|
||||
|
||||
format = getSizedFormat(format, rendertarget, readable);
|
||||
|
||||
return (usage & pixelFormatUsage[format][readable ? 1 : 0]) == usage;
|
||||
}
|
||||
|
||||
|
||||
@@ -106,8 +106,7 @@ public:
|
||||
|
||||
void setWireframe(bool enable) override;
|
||||
|
||||
PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const override;
|
||||
bool isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB = false) override;
|
||||
bool isPixelFormatSupported(PixelFormat format, uint32 usage) override;
|
||||
Renderer getRenderer() const override;
|
||||
bool usesGLSLES() const override;
|
||||
RendererInfo getRendererInfo() const override;
|
||||
|
||||
@@ -91,12 +91,49 @@ OpenGL::TempDebugGroup::~TempDebugGroup()
|
||||
}
|
||||
}
|
||||
|
||||
OpenGL::CleanClearState::CleanClearState(GLbitfield clearFlags)
|
||||
: clearFlags(clearFlags)
|
||||
, colorWriteMask(gl.getColorWriteMask())
|
||||
, stencilWriteMask(gl.getStencilWriteMask())
|
||||
, depthWrites(gl.hasDepthWrites())
|
||||
, scissor(gl.isStateEnabled(ENABLE_SCISSOR_TEST))
|
||||
{
|
||||
if ((clearFlags & GL_COLOR_BUFFER_BIT) != 0 && colorWriteMask != LOVE_UINT32_MAX)
|
||||
gl.setColorWriteMask(LOVE_UINT32_MAX);
|
||||
|
||||
if ((clearFlags & GL_DEPTH_BUFFER_BIT) != 0 && !depthWrites)
|
||||
gl.setDepthWrites(true);
|
||||
|
||||
if ((clearFlags & GL_STENCIL_BUFFER_BIT) != 0 && (stencilWriteMask & 0xFF) != 0xFF)
|
||||
gl.setStencilWriteMask(LOVE_UINT32_MAX);
|
||||
|
||||
if (clearFlags != 0 && scissor)
|
||||
gl.setEnableState(ENABLE_SCISSOR_TEST, false);
|
||||
}
|
||||
|
||||
OpenGL::CleanClearState::~CleanClearState()
|
||||
{
|
||||
if ((clearFlags & GL_COLOR_BUFFER_BIT) != 0 && colorWriteMask != LOVE_UINT32_MAX)
|
||||
gl.setColorWriteMask(colorWriteMask);
|
||||
|
||||
if ((clearFlags & GL_DEPTH_BUFFER_BIT) != 0 && !depthWrites)
|
||||
gl.setDepthWrites(depthWrites);
|
||||
|
||||
if ((clearFlags & GL_STENCIL_BUFFER_BIT) != 0 && (stencilWriteMask & 0xFF) != 0xFF)
|
||||
gl.setStencilWriteMask(stencilWriteMask);
|
||||
|
||||
if (clearFlags != 0 && scissor)
|
||||
gl.setEnableState(ENABLE_SCISSOR_TEST, scissor);
|
||||
}
|
||||
|
||||
OpenGL::OpenGL()
|
||||
: stats()
|
||||
, bugs()
|
||||
, contextInitialized(false)
|
||||
, pixelShaderHighpSupported(false)
|
||||
, baseVertexSupported(false)
|
||||
, maxAnisotropy(1.0f)
|
||||
, maxLODBias(0.0f)
|
||||
, max2DTextureSize(0)
|
||||
, max3DTextureSize(0)
|
||||
, maxCubeTextureSize(0)
|
||||
@@ -284,6 +321,7 @@ void OpenGL::setupContext()
|
||||
|
||||
setDepthWrites(state.depthWritesEnabled);
|
||||
setStencilWriteMask(state.stencilWriteMask);
|
||||
setColorWriteMask(state.colorWriteMask);
|
||||
|
||||
createDefaultTexture();
|
||||
|
||||
@@ -608,11 +646,9 @@ void OpenGL::createDefaultTexture()
|
||||
|
||||
const GLubyte *p = datatype == DATA_BASETYPE_FLOAT ? pix : intpix;
|
||||
|
||||
bool isSRGB = false;
|
||||
rawTexStorage(type, 1, format, isSRGB, 1, 1);
|
||||
|
||||
TextureFormat fmt = convertPixelFormat(format, false, isSRGB);
|
||||
rawTexStorage(type, 1, format, 1, 1);
|
||||
|
||||
TextureFormat fmt = convertPixelFormat(format, false);
|
||||
int slices = type == TEXTURE_CUBE ? 6 : 1;
|
||||
|
||||
for (int slice = 0; slice < slices; slice++)
|
||||
@@ -1125,6 +1161,17 @@ uint32 OpenGL::getStencilWriteMask() const
|
||||
return state.stencilWriteMask;
|
||||
}
|
||||
|
||||
void OpenGL::setColorWriteMask(uint32 mask)
|
||||
{
|
||||
glColorMask(mask & (1 << 0), mask & (1 << 1), mask & (1 << 2), mask & (1 << 3));
|
||||
state.colorWriteMask = mask;
|
||||
}
|
||||
|
||||
uint32 OpenGL::getColorWriteMask() const
|
||||
{
|
||||
return state.colorWriteMask;
|
||||
}
|
||||
|
||||
void OpenGL::useProgram(GLuint program)
|
||||
{
|
||||
glUseProgram(program);
|
||||
@@ -1384,10 +1431,10 @@ void OpenGL::setSamplerState(TextureType target, SamplerState &s)
|
||||
}
|
||||
}
|
||||
|
||||
bool OpenGL::rawTexStorage(TextureType target, int levels, PixelFormat pixelformat, bool &isSRGB, int width, int height, int depth)
|
||||
bool OpenGL::rawTexStorage(TextureType target, int levels, PixelFormat pixelformat, int width, int height, int depth)
|
||||
{
|
||||
GLenum gltarget = getGLTextureType(target);
|
||||
TextureFormat fmt = convertPixelFormat(pixelformat, false, isSRGB);
|
||||
TextureFormat fmt = convertPixelFormat(pixelformat, false);
|
||||
|
||||
// This shouldn't be needed for glTexStorage, but some drivers don't follow
|
||||
// the spec apparently.
|
||||
@@ -1651,16 +1698,14 @@ OpenGL::Vendor OpenGL::getVendor() const
|
||||
return vendor;
|
||||
}
|
||||
|
||||
OpenGL::TextureFormat OpenGL::convertPixelFormat(PixelFormat pixelformat, bool renderbuffer, bool &isSRGB)
|
||||
OpenGL::TextureFormat OpenGL::convertPixelFormat(PixelFormat pixelformat, bool renderbuffer)
|
||||
{
|
||||
TextureFormat f;
|
||||
|
||||
f.framebufferAttachments[0] = GL_COLOR_ATTACHMENT0;
|
||||
f.framebufferAttachments[1] = GL_NONE;
|
||||
|
||||
if (isSRGB)
|
||||
pixelformat = getSRGBPixelFormat(pixelformat);
|
||||
else if (pixelformat == PIXELFORMAT_ETC1_UNORM)
|
||||
if (pixelformat == PIXELFORMAT_ETC1_UNORM)
|
||||
{
|
||||
// The ETC2 format can load ETC1 textures.
|
||||
if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_4_3 || GLAD_ARB_ES3_compatibility)
|
||||
@@ -1693,7 +1738,7 @@ OpenGL::TextureFormat OpenGL::convertPixelFormat(PixelFormat pixelformat, bool r
|
||||
f.externalformat = GL_RGBA;
|
||||
f.type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case PIXELFORMAT_RGBA8_UNORM_sRGB:
|
||||
case PIXELFORMAT_RGBA8_sRGB:
|
||||
f.internalformat = GL_SRGB8_ALPHA8;
|
||||
f.type = GL_UNSIGNED_BYTE;
|
||||
if (GLAD_ES_VERSION_2_0 && !GLAD_ES_VERSION_3_0)
|
||||
@@ -1702,7 +1747,7 @@ OpenGL::TextureFormat OpenGL::convertPixelFormat(PixelFormat pixelformat, bool r
|
||||
f.externalformat = GL_RGBA;
|
||||
break;
|
||||
case PIXELFORMAT_BGRA8_UNORM:
|
||||
case PIXELFORMAT_BGRA8_UNORM_sRGB:
|
||||
case PIXELFORMAT_BGRA8_sRGB:
|
||||
// Not supported right now.
|
||||
break;
|
||||
case PIXELFORMAT_R16_UNORM:
|
||||
@@ -1977,123 +2022,190 @@ OpenGL::TextureFormat OpenGL::convertPixelFormat(PixelFormat pixelformat, bool r
|
||||
break;
|
||||
|
||||
case PIXELFORMAT_DXT1_UNORM:
|
||||
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT : GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||
f.internalformat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||
break;
|
||||
case PIXELFORMAT_DXT1_sRGB:
|
||||
f.internalformat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
|
||||
break;
|
||||
case PIXELFORMAT_DXT3_UNORM:
|
||||
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT : GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||
f.internalformat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||
break;
|
||||
case PIXELFORMAT_DXT3_sRGB:
|
||||
f.internalformat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
|
||||
break;
|
||||
case PIXELFORMAT_DXT5_UNORM:
|
||||
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT : GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||
f.internalformat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||
break;
|
||||
case PIXELFORMAT_DXT5_sRGB:
|
||||
f.internalformat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
|
||||
break;
|
||||
case PIXELFORMAT_BC4_UNORM:
|
||||
isSRGB = false;
|
||||
f.internalformat = GL_COMPRESSED_RED_RGTC1;
|
||||
break;
|
||||
case PIXELFORMAT_BC4_SNORM:
|
||||
isSRGB = false;
|
||||
f.internalformat = GL_COMPRESSED_SIGNED_RED_RGTC1;
|
||||
break;
|
||||
case PIXELFORMAT_BC5_UNORM:
|
||||
isSRGB = false;
|
||||
f.internalformat = GL_COMPRESSED_RG_RGTC2;
|
||||
break;
|
||||
case PIXELFORMAT_BC5_SNORM:
|
||||
isSRGB = false;
|
||||
f.internalformat = GL_COMPRESSED_SIGNED_RG_RGTC2;
|
||||
break;
|
||||
case PIXELFORMAT_BC6H_UFLOAT:
|
||||
isSRGB = false;
|
||||
f.internalformat = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT;
|
||||
break;
|
||||
case PIXELFORMAT_BC6H_FLOAT:
|
||||
isSRGB = false;
|
||||
f.internalformat = GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT;
|
||||
break;
|
||||
case PIXELFORMAT_BC7_UNORM:
|
||||
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM : GL_COMPRESSED_RGBA_BPTC_UNORM;
|
||||
f.internalformat = GL_COMPRESSED_RGBA_BPTC_UNORM;
|
||||
break;
|
||||
case PIXELFORMAT_BC7_sRGB:
|
||||
f.internalformat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM;
|
||||
break;
|
||||
|
||||
case PIXELFORMAT_PVR1_RGB2_UNORM:
|
||||
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT : GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
|
||||
f.internalformat = GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
|
||||
break;
|
||||
case PIXELFORMAT_PVR1_RGB2_sRGB:
|
||||
f.internalformat = GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT;
|
||||
break;
|
||||
case PIXELFORMAT_PVR1_RGB4_UNORM:
|
||||
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT : GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
|
||||
f.internalformat = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
|
||||
break;
|
||||
case PIXELFORMAT_PVR1_RGB4_sRGB:
|
||||
f.internalformat = GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT;
|
||||
break;
|
||||
case PIXELFORMAT_PVR1_RGBA2_UNORM:
|
||||
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT : GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
|
||||
f.internalformat = GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
|
||||
break;
|
||||
case PIXELFORMAT_PVR1_RGBA2_sRGB:
|
||||
f.internalformat = GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT;
|
||||
break;
|
||||
case PIXELFORMAT_PVR1_RGBA4_UNORM:
|
||||
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT : GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
|
||||
f.internalformat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
|
||||
break;
|
||||
case PIXELFORMAT_PVR1_RGBA4_sRGB:
|
||||
f.internalformat = GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT;
|
||||
break;
|
||||
|
||||
case PIXELFORMAT_ETC1_UNORM:
|
||||
isSRGB = false;
|
||||
f.internalformat = GL_ETC1_RGB8_OES;
|
||||
break;
|
||||
case PIXELFORMAT_ETC2_RGB_UNORM:
|
||||
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ETC2 : GL_COMPRESSED_RGB8_ETC2;
|
||||
f.internalformat = GL_COMPRESSED_RGB8_ETC2;
|
||||
break;
|
||||
case PIXELFORMAT_ETC2_RGB_sRGB:
|
||||
f.internalformat = GL_COMPRESSED_SRGB8_ETC2;
|
||||
break;
|
||||
case PIXELFORMAT_ETC2_RGBA_UNORM:
|
||||
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : GL_COMPRESSED_RGBA8_ETC2_EAC;
|
||||
f.internalformat = GL_COMPRESSED_RGBA8_ETC2_EAC;
|
||||
break;
|
||||
case PIXELFORMAT_ETC2_RGBA_sRGB:
|
||||
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC;
|
||||
break;
|
||||
case PIXELFORMAT_ETC2_RGBA1_UNORM:
|
||||
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 : GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
|
||||
f.internalformat = GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
|
||||
break;
|
||||
case PIXELFORMAT_ETC2_RGBA1_sRGB:
|
||||
f.internalformat = GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2;
|
||||
break;
|
||||
case PIXELFORMAT_EAC_R_UNORM:
|
||||
isSRGB = false;
|
||||
f.internalformat = GL_COMPRESSED_R11_EAC;
|
||||
break;
|
||||
case PIXELFORMAT_EAC_R_SNORM:
|
||||
isSRGB = false;
|
||||
f.internalformat = GL_COMPRESSED_SIGNED_R11_EAC;
|
||||
break;
|
||||
case PIXELFORMAT_EAC_RG_UNORM:
|
||||
isSRGB = false;
|
||||
f.internalformat = GL_COMPRESSED_RG11_EAC;
|
||||
break;
|
||||
case PIXELFORMAT_EAC_RG_SNORM:
|
||||
isSRGB = false;
|
||||
f.internalformat = GL_COMPRESSED_SIGNED_RG11_EAC;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_4x4:
|
||||
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : GL_COMPRESSED_RGBA_ASTC_4x4_KHR;
|
||||
|
||||
case PIXELFORMAT_ASTC_4x4_UNORM:
|
||||
f.internalformat = GL_COMPRESSED_RGBA_ASTC_4x4_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_5x4:
|
||||
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : GL_COMPRESSED_RGBA_ASTC_5x4_KHR;
|
||||
case PIXELFORMAT_ASTC_4x4_sRGB:
|
||||
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_5x5:
|
||||
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : GL_COMPRESSED_RGBA_ASTC_5x5_KHR;
|
||||
case PIXELFORMAT_ASTC_5x4_UNORM:
|
||||
f.internalformat = GL_COMPRESSED_RGBA_ASTC_5x4_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_6x5:
|
||||
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : GL_COMPRESSED_RGBA_ASTC_6x5_KHR;
|
||||
case PIXELFORMAT_ASTC_5x4_sRGB:
|
||||
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_6x6:
|
||||
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : GL_COMPRESSED_RGBA_ASTC_6x6_KHR;
|
||||
case PIXELFORMAT_ASTC_5x5_UNORM:
|
||||
f.internalformat = GL_COMPRESSED_RGBA_ASTC_5x5_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_8x5:
|
||||
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : GL_COMPRESSED_RGBA_ASTC_8x5_KHR;
|
||||
case PIXELFORMAT_ASTC_5x5_sRGB:
|
||||
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_8x6:
|
||||
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : GL_COMPRESSED_RGBA_ASTC_8x6_KHR;
|
||||
case PIXELFORMAT_ASTC_6x5_UNORM:
|
||||
f.internalformat = GL_COMPRESSED_RGBA_ASTC_6x5_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_8x8:
|
||||
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : GL_COMPRESSED_RGBA_ASTC_8x8_KHR;
|
||||
case PIXELFORMAT_ASTC_6x5_sRGB:
|
||||
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x5:
|
||||
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : GL_COMPRESSED_RGBA_ASTC_10x5_KHR;
|
||||
case PIXELFORMAT_ASTC_6x6_UNORM:
|
||||
f.internalformat = GL_COMPRESSED_RGBA_ASTC_6x6_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x6:
|
||||
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : GL_COMPRESSED_RGBA_ASTC_10x6_KHR;
|
||||
case PIXELFORMAT_ASTC_6x6_sRGB:
|
||||
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x8:
|
||||
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : GL_COMPRESSED_RGBA_ASTC_10x8_KHR;
|
||||
case PIXELFORMAT_ASTC_8x5_UNORM:
|
||||
f.internalformat = GL_COMPRESSED_RGBA_ASTC_8x5_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x10:
|
||||
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : GL_COMPRESSED_RGBA_ASTC_10x10_KHR;
|
||||
case PIXELFORMAT_ASTC_8x5_sRGB:
|
||||
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_12x10:
|
||||
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : GL_COMPRESSED_RGBA_ASTC_12x10_KHR;
|
||||
case PIXELFORMAT_ASTC_8x6_UNORM:
|
||||
f.internalformat = GL_COMPRESSED_RGBA_ASTC_8x6_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_12x12:
|
||||
f.internalformat = isSRGB ? GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : GL_COMPRESSED_RGBA_ASTC_12x12_KHR;
|
||||
case PIXELFORMAT_ASTC_8x6_sRGB:
|
||||
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_8x8_UNORM:
|
||||
f.internalformat = GL_COMPRESSED_RGBA_ASTC_8x8_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_8x8_sRGB:
|
||||
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x5_UNORM:
|
||||
f.internalformat = GL_COMPRESSED_RGBA_ASTC_10x5_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x5_sRGB:
|
||||
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x6_UNORM:
|
||||
f.internalformat = GL_COMPRESSED_RGBA_ASTC_10x6_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x6_sRGB:
|
||||
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x8_UNORM:
|
||||
f.internalformat = GL_COMPRESSED_RGBA_ASTC_10x8_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x8_sRGB:
|
||||
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x10_UNORM:
|
||||
f.internalformat = GL_COMPRESSED_RGBA_ASTC_10x10_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x10_sRGB:
|
||||
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_12x10_UNORM:
|
||||
f.internalformat = GL_COMPRESSED_RGBA_ASTC_12x10_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_12x10_sRGB:
|
||||
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_12x12_UNORM:
|
||||
f.internalformat = GL_COMPRESSED_RGBA_ASTC_12x12_KHR;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_12x12_sRGB:
|
||||
f.internalformat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -2115,9 +2227,6 @@ OpenGL::TextureFormat OpenGL::convertPixelFormat(PixelFormat pixelformat, bool r
|
||||
{
|
||||
f.internalformat = f.externalformat;
|
||||
}
|
||||
|
||||
if (!isPixelFormatSRGB(pixelformat))
|
||||
isSRGB = false;
|
||||
}
|
||||
|
||||
return f;
|
||||
@@ -2149,7 +2258,7 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat)
|
||||
if (GLAD_VERSION_4_3 || GLAD_ES_VERSION_3_1)
|
||||
flags |= computewrite;
|
||||
break;
|
||||
case PIXELFORMAT_RGBA8_UNORM_sRGB:
|
||||
case PIXELFORMAT_RGBA8_sRGB:
|
||||
if (gl.bugs.brokenSRGB)
|
||||
break;
|
||||
if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_2_1 || GLAD_EXT_texture_sRGB)
|
||||
@@ -2161,7 +2270,7 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat)
|
||||
flags |= computewrite;
|
||||
break;
|
||||
case PIXELFORMAT_BGRA8_UNORM:
|
||||
case PIXELFORMAT_BGRA8_UNORM_sRGB:
|
||||
case PIXELFORMAT_BGRA8_sRGB:
|
||||
// Not supported right now.
|
||||
break;
|
||||
case PIXELFORMAT_R16_UNORM:
|
||||
@@ -2229,47 +2338,47 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat)
|
||||
flags |= computewrite;
|
||||
break;
|
||||
|
||||
case PIXELFORMAT_R8_INT:
|
||||
case PIXELFORMAT_R8_UINT:
|
||||
case PIXELFORMAT_RG8_INT:
|
||||
case PIXELFORMAT_RG8_UINT:
|
||||
case PIXELFORMAT_RGBA8_INT:
|
||||
case PIXELFORMAT_RGBA8_UINT:
|
||||
case PIXELFORMAT_R16_INT:
|
||||
case PIXELFORMAT_R16_UINT:
|
||||
case PIXELFORMAT_RG16_INT:
|
||||
case PIXELFORMAT_RG16_UINT:
|
||||
case PIXELFORMAT_RGBA16_INT:
|
||||
case PIXELFORMAT_RGBA16_UINT:
|
||||
case PIXELFORMAT_R32_INT:
|
||||
case PIXELFORMAT_R32_UINT:
|
||||
case PIXELFORMAT_RG32_INT:
|
||||
case PIXELFORMAT_RG32_UINT:
|
||||
case PIXELFORMAT_RGBA32_INT:
|
||||
case PIXELFORMAT_RGBA32_UINT:
|
||||
if (GLAD_VERSION_3_0 || GLAD_ES_VERSION_3_0)
|
||||
flags |= PIXELFORMATUSAGEFLAGS_SAMPLE | PIXELFORMATUSAGEFLAGS_RENDERTARGET;
|
||||
if (GLAD_VERSION_4_3)
|
||||
flags |= computewrite;
|
||||
if (GLAD_ES_VERSION_3_1)
|
||||
case PIXELFORMAT_R8_INT:
|
||||
case PIXELFORMAT_R8_UINT:
|
||||
case PIXELFORMAT_RG8_INT:
|
||||
case PIXELFORMAT_RG8_UINT:
|
||||
case PIXELFORMAT_RGBA8_INT:
|
||||
case PIXELFORMAT_RGBA8_UINT:
|
||||
case PIXELFORMAT_R16_INT:
|
||||
case PIXELFORMAT_R16_UINT:
|
||||
case PIXELFORMAT_RG16_INT:
|
||||
case PIXELFORMAT_RG16_UINT:
|
||||
case PIXELFORMAT_RGBA16_INT:
|
||||
case PIXELFORMAT_RGBA16_UINT:
|
||||
case PIXELFORMAT_R32_INT:
|
||||
case PIXELFORMAT_R32_UINT:
|
||||
case PIXELFORMAT_RG32_INT:
|
||||
case PIXELFORMAT_RG32_UINT:
|
||||
case PIXELFORMAT_RGBA32_INT:
|
||||
case PIXELFORMAT_RGBA32_UINT:
|
||||
if (GLAD_VERSION_3_0 || GLAD_ES_VERSION_3_0)
|
||||
flags |= PIXELFORMATUSAGEFLAGS_SAMPLE | PIXELFORMATUSAGEFLAGS_RENDERTARGET;
|
||||
if (GLAD_VERSION_4_3)
|
||||
flags |= computewrite;
|
||||
if (GLAD_ES_VERSION_3_1)
|
||||
{
|
||||
switch (pixelformat)
|
||||
{
|
||||
switch (pixelformat)
|
||||
{
|
||||
case PIXELFORMAT_RGBA8_INT:
|
||||
case PIXELFORMAT_RGBA8_UINT:
|
||||
case PIXELFORMAT_RGBA16_INT:
|
||||
case PIXELFORMAT_RGBA16_UINT:
|
||||
case PIXELFORMAT_R32_INT:
|
||||
case PIXELFORMAT_R32_UINT:
|
||||
case PIXELFORMAT_RGBA32_INT:
|
||||
case PIXELFORMAT_RGBA32_UINT:
|
||||
flags |= computewrite;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case PIXELFORMAT_RGBA8_INT:
|
||||
case PIXELFORMAT_RGBA8_UINT:
|
||||
case PIXELFORMAT_RGBA16_INT:
|
||||
case PIXELFORMAT_RGBA16_UINT:
|
||||
case PIXELFORMAT_R32_INT:
|
||||
case PIXELFORMAT_R32_UINT:
|
||||
case PIXELFORMAT_RGBA32_INT:
|
||||
case PIXELFORMAT_RGBA32_UINT:
|
||||
flags |= computewrite;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case PIXELFORMAT_LA8_UNORM:
|
||||
flags |= commonsample;
|
||||
@@ -2331,14 +2440,17 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat)
|
||||
break;
|
||||
|
||||
case PIXELFORMAT_DXT1_UNORM:
|
||||
case PIXELFORMAT_DXT1_sRGB:
|
||||
if (GLAD_EXT_texture_compression_s3tc || GLAD_EXT_texture_compression_dxt1)
|
||||
flags |= commonsample;
|
||||
break;
|
||||
case PIXELFORMAT_DXT3_UNORM:
|
||||
case PIXELFORMAT_DXT3_sRGB:
|
||||
if (GLAD_EXT_texture_compression_s3tc || GLAD_ANGLE_texture_compression_dxt3)
|
||||
flags |= commonsample;
|
||||
break;
|
||||
case PIXELFORMAT_DXT5_UNORM:
|
||||
case PIXELFORMAT_DXT5_sRGB:
|
||||
if (GLAD_EXT_texture_compression_s3tc || GLAD_ANGLE_texture_compression_dxt5)
|
||||
flags |= commonsample;
|
||||
break;
|
||||
@@ -2352,6 +2464,7 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat)
|
||||
case PIXELFORMAT_BC6H_UFLOAT:
|
||||
case PIXELFORMAT_BC6H_FLOAT:
|
||||
case PIXELFORMAT_BC7_UNORM:
|
||||
case PIXELFORMAT_BC7_sRGB:
|
||||
if (GLAD_VERSION_4_2 || GLAD_ARB_texture_compression_bptc)
|
||||
flags |= commonsample;
|
||||
break;
|
||||
@@ -2362,14 +2475,24 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat)
|
||||
if (GLAD_IMG_texture_compression_pvrtc)
|
||||
flags |= commonsample;
|
||||
break;
|
||||
case PIXELFORMAT_PVR1_RGB2_sRGB:
|
||||
case PIXELFORMAT_PVR1_RGB4_sRGB:
|
||||
case PIXELFORMAT_PVR1_RGBA2_sRGB:
|
||||
case PIXELFORMAT_PVR1_RGBA4_sRGB:
|
||||
if (GLAD_EXT_pvrtc_sRGB)
|
||||
flags |= commonsample;
|
||||
break;
|
||||
case PIXELFORMAT_ETC1_UNORM:
|
||||
// ETC2 support guarantees ETC1 support as well.
|
||||
if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_4_3 || GLAD_ARB_ES3_compatibility || GLAD_OES_compressed_ETC1_RGB8_texture)
|
||||
flags |= commonsample;
|
||||
break;
|
||||
case PIXELFORMAT_ETC2_RGB_UNORM:
|
||||
case PIXELFORMAT_ETC2_RGB_sRGB:
|
||||
case PIXELFORMAT_ETC2_RGBA_UNORM:
|
||||
case PIXELFORMAT_ETC2_RGBA_sRGB:
|
||||
case PIXELFORMAT_ETC2_RGBA1_UNORM:
|
||||
case PIXELFORMAT_ETC2_RGBA1_sRGB:
|
||||
case PIXELFORMAT_EAC_R_UNORM:
|
||||
case PIXELFORMAT_EAC_R_SNORM:
|
||||
case PIXELFORMAT_EAC_RG_UNORM:
|
||||
@@ -2377,20 +2500,34 @@ uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat)
|
||||
if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_4_3 || GLAD_ARB_ES3_compatibility)
|
||||
flags |= commonsample;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_4x4:
|
||||
case PIXELFORMAT_ASTC_5x4:
|
||||
case PIXELFORMAT_ASTC_5x5:
|
||||
case PIXELFORMAT_ASTC_6x5:
|
||||
case PIXELFORMAT_ASTC_6x6:
|
||||
case PIXELFORMAT_ASTC_8x5:
|
||||
case PIXELFORMAT_ASTC_8x6:
|
||||
case PIXELFORMAT_ASTC_8x8:
|
||||
case PIXELFORMAT_ASTC_10x5:
|
||||
case PIXELFORMAT_ASTC_10x6:
|
||||
case PIXELFORMAT_ASTC_10x8:
|
||||
case PIXELFORMAT_ASTC_10x10:
|
||||
case PIXELFORMAT_ASTC_12x10:
|
||||
case PIXELFORMAT_ASTC_12x12:
|
||||
case PIXELFORMAT_ASTC_4x4_UNORM:
|
||||
case PIXELFORMAT_ASTC_5x4_UNORM:
|
||||
case PIXELFORMAT_ASTC_5x5_UNORM:
|
||||
case PIXELFORMAT_ASTC_6x5_UNORM:
|
||||
case PIXELFORMAT_ASTC_6x6_UNORM:
|
||||
case PIXELFORMAT_ASTC_8x5_UNORM:
|
||||
case PIXELFORMAT_ASTC_8x6_UNORM:
|
||||
case PIXELFORMAT_ASTC_8x8_UNORM:
|
||||
case PIXELFORMAT_ASTC_10x5_UNORM:
|
||||
case PIXELFORMAT_ASTC_10x6_UNORM:
|
||||
case PIXELFORMAT_ASTC_10x8_UNORM:
|
||||
case PIXELFORMAT_ASTC_10x10_UNORM:
|
||||
case PIXELFORMAT_ASTC_12x10_UNORM:
|
||||
case PIXELFORMAT_ASTC_12x12_UNORM:
|
||||
case PIXELFORMAT_ASTC_4x4_sRGB:
|
||||
case PIXELFORMAT_ASTC_5x4_sRGB:
|
||||
case PIXELFORMAT_ASTC_5x5_sRGB:
|
||||
case PIXELFORMAT_ASTC_6x5_sRGB:
|
||||
case PIXELFORMAT_ASTC_6x6_sRGB:
|
||||
case PIXELFORMAT_ASTC_8x5_sRGB:
|
||||
case PIXELFORMAT_ASTC_8x6_sRGB:
|
||||
case PIXELFORMAT_ASTC_8x8_sRGB:
|
||||
case PIXELFORMAT_ASTC_10x5_sRGB:
|
||||
case PIXELFORMAT_ASTC_10x6_sRGB:
|
||||
case PIXELFORMAT_ASTC_10x8_sRGB:
|
||||
case PIXELFORMAT_ASTC_10x10_sRGB:
|
||||
case PIXELFORMAT_ASTC_12x10_sRGB:
|
||||
case PIXELFORMAT_ASTC_12x12_sRGB:
|
||||
if (GLAD_ES_VERSION_3_2 || GLAD_KHR_texture_compression_astc_ldr)
|
||||
flags |= commonsample;
|
||||
break;
|
||||
|
||||
@@ -124,6 +124,21 @@ public:
|
||||
~TempDebugGroup();
|
||||
};
|
||||
|
||||
// glClear() is affected by various OpenGL state...
|
||||
class CleanClearState
|
||||
{
|
||||
public:
|
||||
CleanClearState(GLbitfield clearFlags);
|
||||
~CleanClearState();
|
||||
|
||||
private:
|
||||
GLenum clearFlags;
|
||||
uint32 colorWriteMask;
|
||||
uint32 stencilWriteMask;
|
||||
bool depthWrites;
|
||||
bool scissor;
|
||||
};
|
||||
|
||||
struct Stats
|
||||
{
|
||||
int shaderSwitches;
|
||||
@@ -301,6 +316,9 @@ public:
|
||||
void setStencilWriteMask(uint32 mask);
|
||||
uint32 getStencilWriteMask() const;
|
||||
|
||||
void setColorWriteMask(uint32 mask);
|
||||
uint32 getColorWriteMask() const;
|
||||
|
||||
/**
|
||||
* Calls glUseProgram.
|
||||
**/
|
||||
@@ -363,7 +381,7 @@ public:
|
||||
* to glTexImage2D/3D for all levels and slices of a texture otherwise.
|
||||
* NOTE: this does not handle compressed texture formats.
|
||||
**/
|
||||
bool rawTexStorage(TextureType target, int levels, PixelFormat pixelformat, bool &isSRGB, int width, int height, int depth = 1);
|
||||
bool rawTexStorage(TextureType target, int levels, PixelFormat pixelformat, int width, int height, int depth = 1);
|
||||
|
||||
bool isTextureTypeSupported(TextureType type) const;
|
||||
bool isBufferUsageSupported(BufferUsage usage) const;
|
||||
@@ -457,7 +475,7 @@ public:
|
||||
static GLint getGLWrapMode(SamplerState::WrapMode wmode);
|
||||
static GLint getGLCompareMode(CompareMode mode);
|
||||
|
||||
static TextureFormat convertPixelFormat(PixelFormat pixelformat, bool renderbuffer, bool &isSRGB);
|
||||
static TextureFormat convertPixelFormat(PixelFormat pixelformat, bool renderbuffer);
|
||||
static bool isTexStorageSupported();
|
||||
static uint32 getPixelFormatUsageFlags(PixelFormat pixelformat);
|
||||
|
||||
@@ -528,6 +546,7 @@ private:
|
||||
|
||||
bool depthWritesEnabled = true;
|
||||
uint32 stencilWriteMask = LOVE_UINT32_MAX;
|
||||
uint32 colorWriteMask = LOVE_UINT32_MAX;
|
||||
|
||||
GLuint boundFramebuffers[2];
|
||||
|
||||
|
||||
@@ -175,8 +175,7 @@ void Shader::mapActiveUniforms()
|
||||
else if ((u.access & ACCESS_READ) != 0)
|
||||
binding.access = GL_READ_ONLY;
|
||||
|
||||
bool sRGB = false;
|
||||
auto fmt = OpenGL::convertPixelFormat(u.storageTextureFormat, false, sRGB);
|
||||
auto fmt = OpenGL::convertPixelFormat(u.storageTextureFormat, false);
|
||||
binding.internalFormat = fmt.internalformat;
|
||||
|
||||
for (int i = 0; i < u.count; i++)
|
||||
|
||||
@@ -56,8 +56,7 @@ static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat fo
|
||||
glReadBuffer(GL_NONE);
|
||||
}
|
||||
|
||||
bool unusedSRGB = false;
|
||||
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(format, false, unusedSRGB);
|
||||
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(format, false);
|
||||
|
||||
int faces = texType == TEXTURE_CUBE ? 6 : 1;
|
||||
|
||||
@@ -78,33 +77,38 @@ static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat fo
|
||||
gl.framebufferTexture(attachment, texType, texture, mip, layer, face);
|
||||
}
|
||||
|
||||
if (clear)
|
||||
if (clear && isPixelFormatInteger(format))
|
||||
{
|
||||
if (isPixelFormatDepthStencil(format))
|
||||
PixelFormatType datatype = getPixelFormatInfo(format).dataType;
|
||||
if (datatype == PIXELFORMATTYPE_SINT)
|
||||
{
|
||||
bool hadDepthWrites = gl.hasDepthWrites();
|
||||
if (!hadDepthWrites) // glDepthMask also affects glClear.
|
||||
gl.setDepthWrites(true);
|
||||
const GLint carray[] = { 0, 0, 0, 0 };
|
||||
glClearBufferiv(GL_COLOR, 0, carray);
|
||||
}
|
||||
else
|
||||
{
|
||||
const GLuint carray[] = { 0, 0, 0, 0 };
|
||||
glClearBufferuiv(GL_COLOR, 0, carray);
|
||||
}
|
||||
}
|
||||
else if (clear)
|
||||
{
|
||||
bool ds = isPixelFormatDepthStencil(format);
|
||||
|
||||
uint32 stencilwrite = gl.getStencilWriteMask();
|
||||
if (stencilwrite != LOVE_UINT32_MAX)
|
||||
gl.setStencilWriteMask(LOVE_UINT32_MAX);
|
||||
GLbitfield clearflags = ds ? GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT : GL_COLOR_BUFFER_BIT;
|
||||
OpenGL::CleanClearState cleanClearState(clearflags);
|
||||
|
||||
if (ds)
|
||||
{
|
||||
gl.clearDepth(1.0);
|
||||
glClearStencil(0);
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
if (!hadDepthWrites)
|
||||
gl.setDepthWrites(hadDepthWrites);
|
||||
|
||||
if (stencilwrite != LOVE_UINT32_MAX)
|
||||
gl.setStencilWriteMask(stencilwrite);
|
||||
}
|
||||
else
|
||||
{
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
glClear(clearflags);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -120,8 +124,7 @@ static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat fo
|
||||
|
||||
static GLenum newRenderbuffer(int width, int height, int &samples, PixelFormat pixelformat, GLuint &buffer)
|
||||
{
|
||||
bool unusedSRGB = false;
|
||||
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(pixelformat, true, unusedSRGB);
|
||||
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(pixelformat, true);
|
||||
|
||||
GLuint current_fbo = gl.getFramebuffer(OpenGL::FRAMEBUFFER_ALL);
|
||||
|
||||
@@ -167,24 +170,39 @@ static GLenum newRenderbuffer(int width, int height, int &samples, PixelFormat p
|
||||
|
||||
if (status == GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
if (isPixelFormatDepthStencil(pixelformat))
|
||||
if (isPixelFormatInteger(pixelformat))
|
||||
{
|
||||
bool hadDepthWrites = gl.hasDepthWrites();
|
||||
if (!hadDepthWrites) // glDepthMask also affects glClear.
|
||||
gl.setDepthWrites(true);
|
||||
|
||||
gl.clearDepth(1.0);
|
||||
glClearStencil(0);
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
if (!hadDepthWrites)
|
||||
gl.setDepthWrites(hadDepthWrites);
|
||||
PixelFormatType datatype = getPixelFormatInfo(pixelformat).dataType;
|
||||
if (datatype == PIXELFORMATTYPE_SINT)
|
||||
{
|
||||
const GLint carray[] = { 0, 0, 0, 0 };
|
||||
glClearBufferiv(GL_COLOR, 0, carray);
|
||||
}
|
||||
else
|
||||
{
|
||||
const GLuint carray[] = { 0, 0, 0, 0 };
|
||||
glClearBufferuiv(GL_COLOR, 0, carray);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Initialize the buffer to transparent black.
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
bool ds = isPixelFormatDepthStencil(pixelformat);
|
||||
|
||||
GLbitfield clearflags = ds ? GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT : GL_COLOR_BUFFER_BIT;
|
||||
OpenGL::CleanClearState cleanClearState(clearflags);
|
||||
|
||||
if (ds)
|
||||
{
|
||||
gl.clearDepth(1.0);
|
||||
glClearStencil(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Initialize the buffer to transparent black.
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
glClear(clearflags);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -262,7 +280,7 @@ void Texture::createTexture()
|
||||
// remember some driver issues on some old Android systems, maybe...
|
||||
// For now, the base class enforces data on init for compressed textures.
|
||||
if (!isCompressed())
|
||||
gl.rawTexStorage(texType, mipcount, format, sRGB, pixelWidth, pixelHeight, texType == TEXTURE_VOLUME ? depth : layers);
|
||||
gl.rawTexStorage(texType, mipcount, format, pixelWidth, pixelHeight, texType == TEXTURE_VOLUME ? depth : layers);
|
||||
|
||||
// rawTexStorage handles this for uncompressed textures.
|
||||
if (isCompressed() && (GLAD_VERSION_1_1 || GLAD_ES_VERSION_3_0))
|
||||
@@ -272,7 +290,7 @@ void Texture::createTexture()
|
||||
int h = pixelHeight;
|
||||
int d = depth;
|
||||
|
||||
OpenGL::TextureFormat fmt = gl.convertPixelFormat(format, false, sRGB);
|
||||
OpenGL::TextureFormat fmt = gl.convertPixelFormat(format, false);
|
||||
|
||||
for (int mip = 0; mip < mipcount; mip++)
|
||||
{
|
||||
@@ -440,7 +458,7 @@ void Texture::uploadByteData(PixelFormat pixelformat, const void *data, size_t s
|
||||
|
||||
gl.bindTextureToUnit(this, 0, false);
|
||||
|
||||
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(pixelformat, false, sRGB);
|
||||
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(pixelformat, false);
|
||||
GLenum gltarget = OpenGL::getGLTextureType(texType);
|
||||
|
||||
if (texType == TEXTURE_CUBE)
|
||||
@@ -488,8 +506,7 @@ void Texture::readbackInternal(int slice, int mipmap, const Rect &rect, int dest
|
||||
|
||||
gl.bindTextureToUnit(this, 0, false);
|
||||
|
||||
bool isSRGB = false;
|
||||
OpenGL::TextureFormat fmt = gl.convertPixelFormat(format, false, isSRGB);
|
||||
OpenGL::TextureFormat fmt = gl.convertPixelFormat(format, false);
|
||||
|
||||
if (gl.isCopyTextureToBufferSupported())
|
||||
{
|
||||
|
||||
@@ -65,29 +65,100 @@ const char *Graphics::getName() const
|
||||
return "love.graphics.vulkan";
|
||||
}
|
||||
|
||||
const VkDevice Graphics::getDevice() const
|
||||
VkDevice Graphics::getDevice() const
|
||||
{
|
||||
return device;
|
||||
}
|
||||
|
||||
const VmaAllocator Graphics::getVmaAllocator() const
|
||||
VmaAllocator Graphics::getVmaAllocator() const
|
||||
{
|
||||
return vmaAllocator;
|
||||
}
|
||||
|
||||
static void checkOptionalInstanceExtensions(OptionalInstanceExtensions& ext)
|
||||
{
|
||||
uint32_t count;
|
||||
|
||||
vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr);
|
||||
|
||||
std::vector<VkExtensionProperties> extensions(count);
|
||||
|
||||
vkEnumerateInstanceExtensionProperties(nullptr, &count, extensions.data());
|
||||
|
||||
for (const auto& extension : extensions)
|
||||
{
|
||||
if (strcmp(extension.extensionName, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) == 0)
|
||||
ext.physicalDeviceProperties2 = true;
|
||||
}
|
||||
}
|
||||
|
||||
Graphics::Graphics()
|
||||
{
|
||||
if (SDL_Vulkan_LoadLibrary(nullptr))
|
||||
throw love::Exception("could not find vulkan");
|
||||
|
||||
volkInitializeCustom((PFN_vkGetInstanceProcAddr)SDL_Vulkan_GetVkGetInstanceProcAddr());
|
||||
|
||||
if (isDebugEnabled() && !checkValidationSupport())
|
||||
throw love::Exception("validation layers requested, but not available");
|
||||
|
||||
VkApplicationInfo appInfo{};
|
||||
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||
appInfo.pApplicationName = "LOVE";
|
||||
appInfo.applicationVersion = VK_MAKE_API_VERSION(0, 1, 0, 0); // get this version from somewhere else?
|
||||
appInfo.pEngineName = "LOVE Game Framework";
|
||||
appInfo.engineVersion = VK_MAKE_API_VERSION(0, VERSION_MAJOR, VERSION_MINOR, VERSION_REV);
|
||||
appInfo.apiVersion = VK_API_VERSION_1_3;
|
||||
|
||||
VkInstanceCreateInfo createInfo{};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||
createInfo.pApplicationInfo = &appInfo;
|
||||
createInfo.pNext = nullptr;
|
||||
|
||||
// GetInstanceExtensions works with a null window parameter as long as
|
||||
// SDL_Vulkan_LoadLibrary has been called (which we do earlier).
|
||||
unsigned int count;
|
||||
if (SDL_Vulkan_GetInstanceExtensions(nullptr, &count, nullptr) != SDL_TRUE)
|
||||
throw love::Exception("couldn't retrieve sdl vulkan extensions");
|
||||
|
||||
std::vector<const char*> extensions = {};
|
||||
|
||||
checkOptionalInstanceExtensions(optionalInstanceExtensions);
|
||||
|
||||
if (optionalInstanceExtensions.physicalDeviceProperties2)
|
||||
extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
||||
|
||||
size_t additional_extension_count = extensions.size();
|
||||
extensions.resize(additional_extension_count + count);
|
||||
|
||||
if (SDL_Vulkan_GetInstanceExtensions(nullptr, &count, extensions.data() + additional_extension_count) != SDL_TRUE)
|
||||
throw love::Exception("couldn't retrieve sdl vulkan extensions");
|
||||
|
||||
createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
|
||||
createInfo.ppEnabledExtensionNames = extensions.data();
|
||||
|
||||
if (isDebugEnabled())
|
||||
{
|
||||
createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
|
||||
createInfo.ppEnabledLayerNames = validationLayers.data();
|
||||
}
|
||||
|
||||
if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS)
|
||||
throw love::Exception("couldn't create vulkan instance");
|
||||
|
||||
volkLoadInstance(instance);
|
||||
}
|
||||
|
||||
Graphics::~Graphics()
|
||||
{
|
||||
defaultConstantTexCoord.set(nullptr);
|
||||
defaultConstantColor.set(nullptr);
|
||||
defaultTexture.set(nullptr);
|
||||
|
||||
Volatile::unloadAll();
|
||||
cleanup();
|
||||
vkDestroyInstance(instance, nullptr);
|
||||
|
||||
SDL_Vulkan_UnloadLibrary();
|
||||
}
|
||||
|
||||
@@ -302,14 +373,14 @@ void Graphics::discard(const std::vector<bool> &colorbuffers, bool depthstencil)
|
||||
startRenderPass();
|
||||
}
|
||||
|
||||
void Graphics::submitGpuCommands(bool present, void *screenshotCallbackData)
|
||||
void Graphics::submitGpuCommands(SubmitMode submitMode, void *screenshotCallbackData)
|
||||
{
|
||||
flushBatchedDraws();
|
||||
|
||||
if (renderPassState.active)
|
||||
endRenderPass();
|
||||
|
||||
if (present)
|
||||
if (submitMode == SUBMIT_PRESENT)
|
||||
{
|
||||
if (pendingScreenshotCallbacks.empty())
|
||||
Vulkan::cmdTransitionImageLayout(
|
||||
@@ -435,7 +506,7 @@ void Graphics::submitGpuCommands(bool present, void *screenshotCallbackData)
|
||||
|
||||
VkFence fence = VK_NULL_HANDLE;
|
||||
|
||||
if (present)
|
||||
if (submitMode == SUBMIT_PRESENT)
|
||||
{
|
||||
submitInfo.signalSemaphoreCount = 1;
|
||||
submitInfo.pSignalSemaphores = signalSemaphores;
|
||||
@@ -447,7 +518,7 @@ void Graphics::submitGpuCommands(bool present, void *screenshotCallbackData)
|
||||
if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, fence) != VK_SUCCESS)
|
||||
throw love::Exception("failed to submit draw command buffer");
|
||||
|
||||
if (!present)
|
||||
if (submitMode == SUBMIT_NOPRESENT || submitMode == SUBMIT_RESTART)
|
||||
{
|
||||
vkQueueWaitIdle(graphicsQueue);
|
||||
|
||||
@@ -458,7 +529,8 @@ void Graphics::submitGpuCommands(bool present, void *screenshotCallbackData)
|
||||
callbacks.clear();
|
||||
}
|
||||
|
||||
startRecordingGraphicsCommands();
|
||||
if (submitMode == SUBMIT_RESTART)
|
||||
startRecordingGraphicsCommands();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -475,7 +547,7 @@ void Graphics::present(void *screenshotCallbackdata)
|
||||
|
||||
deprecations.draw(this);
|
||||
|
||||
submitGpuCommands(true, screenshotCallbackdata);
|
||||
submitGpuCommands(SUBMIT_PRESENT, screenshotCallbackdata);
|
||||
|
||||
VkPresentInfoKHR presentInfo{};
|
||||
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||
@@ -540,64 +612,80 @@ bool Graphics::setMode(void *context, int width, int height, int pixelwidth, int
|
||||
readbackCallbacks.clear();
|
||||
readbackCallbacks.resize(MAX_FRAMES_IN_FLIGHT);
|
||||
|
||||
createVulkanInstance();
|
||||
bool createBaseObjects = physicalDevice == VK_NULL_HANDLE;
|
||||
|
||||
createSurface();
|
||||
pickPhysicalDevice();
|
||||
createLogicalDevice();
|
||||
createPipelineCache();
|
||||
initVMA();
|
||||
initCapabilities();
|
||||
|
||||
if (createBaseObjects)
|
||||
{
|
||||
pickPhysicalDevice();
|
||||
createLogicalDevice();
|
||||
createPipelineCache();
|
||||
initVMA();
|
||||
initCapabilities();
|
||||
}
|
||||
|
||||
msaaSamples = getMsaaCount(requestedMsaa);
|
||||
|
||||
createSwapChain();
|
||||
createImageViews();
|
||||
createScreenshotCallbackBuffers();
|
||||
createSyncObjects();
|
||||
createColorResources();
|
||||
createDepthResources();
|
||||
transitionColorDepthLayouts = true;
|
||||
createCommandPool();
|
||||
createCommandBuffers();
|
||||
|
||||
if (createBaseObjects)
|
||||
{
|
||||
createCommandPool();
|
||||
createCommandBuffers();
|
||||
createSyncObjects();
|
||||
}
|
||||
|
||||
beginFrame();
|
||||
|
||||
if (batchedDrawState.vb[0] == nullptr)
|
||||
if (createBaseObjects)
|
||||
{
|
||||
// Initial sizes that should be good enough for most cases. It will
|
||||
// resize to fit if needed, later.
|
||||
batchedDrawState.vb[0] = new StreamBuffer(this, BUFFERUSAGE_VERTEX, 1024 * 1024 * 1);
|
||||
batchedDrawState.vb[1] = new StreamBuffer(this, BUFFERUSAGE_VERTEX, 256 * 1024 * 1);
|
||||
batchedDrawState.indexBuffer = new StreamBuffer(this, BUFFERUSAGE_INDEX, sizeof(uint16) * LOVE_UINT16_MAX);
|
||||
}
|
||||
if (batchedDrawState.vb[0] == nullptr)
|
||||
{
|
||||
// Initial sizes that should be good enough for most cases. It will
|
||||
// resize to fit if needed, later.
|
||||
batchedDrawState.vb[0] = new StreamBuffer(this, BUFFERUSAGE_VERTEX, 1024 * 1024 * 1);
|
||||
batchedDrawState.vb[1] = new StreamBuffer(this, BUFFERUSAGE_VERTEX, 256 * 1024 * 1);
|
||||
batchedDrawState.indexBuffer = new StreamBuffer(this, BUFFERUSAGE_INDEX, sizeof(uint16) * LOVE_UINT16_MAX);
|
||||
}
|
||||
|
||||
// sometimes the VertexTexCoord is not set, so we manually adjust it to (0, 0)
|
||||
if (defaultConstantTexCoord == nullptr)
|
||||
{
|
||||
float zeroTexCoord[2] = { 0.0f, 0.0f };
|
||||
Buffer::DataDeclaration format("ConstantTexCoord", DATAFORMAT_FLOAT_VEC2);
|
||||
Buffer::Settings settings(BUFFERUSAGEFLAG_VERTEX, BUFFERDATAUSAGE_STATIC);
|
||||
defaultConstantTexCoord = newBuffer(settings, { format }, zeroTexCoord, sizeof(zeroTexCoord), 1);
|
||||
}
|
||||
// sometimes the VertexTexCoord is not set, so we manually adjust it to (0, 0)
|
||||
if (defaultConstantTexCoord == nullptr)
|
||||
{
|
||||
float zeroTexCoord[2] = { 0.0f, 0.0f };
|
||||
Buffer::DataDeclaration format("ConstantTexCoord", DATAFORMAT_FLOAT_VEC2);
|
||||
Buffer::Settings settings(BUFFERUSAGEFLAG_VERTEX, BUFFERDATAUSAGE_STATIC);
|
||||
defaultConstantTexCoord = newBuffer(settings, { format }, zeroTexCoord, sizeof(zeroTexCoord), 1);
|
||||
}
|
||||
|
||||
// sometimes the VertexColor is not set, so we manually adjust it to white color
|
||||
if (defaultConstantColor == nullptr)
|
||||
{
|
||||
uint8 whiteColor[] = { 255, 255, 255, 255 };
|
||||
Buffer::DataDeclaration format("ConstantColor", DATAFORMAT_UNORM8_VEC4);
|
||||
Buffer::Settings settings(BUFFERUSAGEFLAG_VERTEX, BUFFERDATAUSAGE_STATIC);
|
||||
defaultConstantColor = newBuffer(settings, { format }, whiteColor, sizeof(whiteColor), 1);
|
||||
}
|
||||
// sometimes the VertexColor is not set, so we manually adjust it to white color
|
||||
if (defaultConstantColor == nullptr)
|
||||
{
|
||||
uint8 whiteColor[] = { 255, 255, 255, 255 };
|
||||
Buffer::DataDeclaration format("ConstantColor", DATAFORMAT_UNORM8_VEC4);
|
||||
Buffer::Settings settings(BUFFERUSAGEFLAG_VERTEX, BUFFERDATAUSAGE_STATIC);
|
||||
defaultConstantColor = newBuffer(settings, { format }, whiteColor, sizeof(whiteColor), 1);
|
||||
}
|
||||
|
||||
createDefaultTexture();
|
||||
createDefaultShaders();
|
||||
Shader::current = Shader::standardShaders[Shader::StandardShader::STANDARD_DEFAULT];
|
||||
createQuadIndexBuffer();
|
||||
createFanIndexBuffer();
|
||||
createDefaultTexture();
|
||||
createDefaultShaders();
|
||||
Shader::current = Shader::standardShaders[Shader::StandardShader::STANDARD_DEFAULT];
|
||||
createQuadIndexBuffer();
|
||||
createFanIndexBuffer();
|
||||
|
||||
frameCounter = 0;
|
||||
currentFrame = 0;
|
||||
}
|
||||
|
||||
restoreState(states.back());
|
||||
|
||||
Vulkan::resetShaderSwitches();
|
||||
|
||||
frameCounter = 0;
|
||||
currentFrame = 0;
|
||||
created = true;
|
||||
drawCalls = 0;
|
||||
drawCallsBatched = 0;
|
||||
@@ -659,14 +747,12 @@ void Graphics::getAPIStats(int &shaderswitches) const
|
||||
|
||||
void Graphics::unSetMode()
|
||||
{
|
||||
renderPassUsages.clear();
|
||||
framebufferUsages.clear();
|
||||
pipelineUsages.clear();
|
||||
|
||||
submitGpuCommands(SUBMIT_NOPRESENT);
|
||||
|
||||
created = false;
|
||||
vkDeviceWaitIdle(device);
|
||||
Volatile::unloadAll();
|
||||
cleanup();
|
||||
|
||||
cleanupSwapChain();
|
||||
vkDestroySurfaceKHR(instance, surface, nullptr);
|
||||
}
|
||||
|
||||
void Graphics::setActive(bool enable)
|
||||
@@ -971,30 +1057,11 @@ void Graphics::setWireframe(bool enable)
|
||||
states.back().wireframe = enable;
|
||||
}
|
||||
|
||||
PixelFormat Graphics::getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const
|
||||
bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case PIXELFORMAT_NORMAL:
|
||||
if (isGammaCorrect())
|
||||
return PIXELFORMAT_RGBA8_UNORM_sRGB;
|
||||
else
|
||||
return PIXELFORMAT_RGBA8_UNORM;
|
||||
case PIXELFORMAT_HDR:
|
||||
return PIXELFORMAT_RGBA16_FLOAT;
|
||||
default:
|
||||
return format;
|
||||
}
|
||||
}
|
||||
format = getSizedFormat(format);
|
||||
|
||||
bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB)
|
||||
{
|
||||
bool rendertarget = (usage & PIXELFORMATUSAGEFLAGS_RENDERTARGET) != 0;
|
||||
bool readable = (usage & PIXELFORMATUSAGEFLAGS_SAMPLE) != 0;
|
||||
|
||||
format = getSizedFormat(format, rendertarget, readable);
|
||||
|
||||
auto vulkanFormat = Vulkan::getTextureFormat(format, sRGB);
|
||||
auto vulkanFormat = Vulkan::getTextureFormat(format);
|
||||
|
||||
VkFormatProperties formatProperties;
|
||||
vkGetPhysicalDeviceFormatProperties(physicalDevice, vulkanFormat.internalFormat, &formatProperties);
|
||||
@@ -1332,75 +1399,6 @@ const OptionalDeviceExtensions &Graphics::getEnabledOptionalDeviceExtensions() c
|
||||
return optionalDeviceExtensions;
|
||||
}
|
||||
|
||||
static void checkOptionalInstanceExtensions(OptionalInstanceExtensions &ext)
|
||||
{
|
||||
uint32_t count;
|
||||
|
||||
vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr);
|
||||
|
||||
std::vector<VkExtensionProperties> extensions(count);
|
||||
|
||||
vkEnumerateInstanceExtensionProperties(nullptr, &count, extensions.data());
|
||||
|
||||
for (const auto &extension : extensions)
|
||||
{
|
||||
if (strcmp(extension.extensionName, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) == 0)
|
||||
ext.physicalDeviceProperties2 = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Graphics::createVulkanInstance()
|
||||
{
|
||||
if (isDebugEnabled() && !checkValidationSupport())
|
||||
throw love::Exception("validation layers requested, but not available");
|
||||
|
||||
VkApplicationInfo appInfo{};
|
||||
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||
appInfo.pApplicationName = "LOVE";
|
||||
appInfo.applicationVersion = VK_MAKE_API_VERSION(0, 1, 0, 0); // get this version from somewhere else?
|
||||
appInfo.pEngineName = "LOVE Game Framework";
|
||||
appInfo.engineVersion = VK_MAKE_API_VERSION(0, VERSION_MAJOR, VERSION_MINOR, VERSION_REV);
|
||||
appInfo.apiVersion = VK_API_VERSION_1_3;
|
||||
|
||||
VkInstanceCreateInfo createInfo{};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||
createInfo.pApplicationInfo = &appInfo;
|
||||
createInfo.pNext = nullptr;
|
||||
|
||||
// GetInstanceExtensions works with a null window parameter as long as
|
||||
// SDL_Vulkan_LoadLibrary has been called (which we do earlier).
|
||||
unsigned int count;
|
||||
if (SDL_Vulkan_GetInstanceExtensions(nullptr, &count, nullptr) != SDL_TRUE)
|
||||
throw love::Exception("couldn't retrieve sdl vulkan extensions");
|
||||
|
||||
std::vector<const char*> extensions = {};
|
||||
|
||||
checkOptionalInstanceExtensions(optionalInstanceExtensions);
|
||||
|
||||
if (optionalInstanceExtensions.physicalDeviceProperties2)
|
||||
extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
||||
|
||||
size_t additional_extension_count = extensions.size();
|
||||
extensions.resize(additional_extension_count + count);
|
||||
|
||||
if (SDL_Vulkan_GetInstanceExtensions(nullptr, &count, extensions.data() + additional_extension_count) != SDL_TRUE)
|
||||
throw love::Exception("couldn't retrieve sdl vulkan extensions");
|
||||
|
||||
createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
|
||||
createInfo.ppEnabledExtensionNames = extensions.data();
|
||||
|
||||
if (isDebugEnabled())
|
||||
{
|
||||
createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
|
||||
createInfo.ppEnabledLayerNames = validationLayers.data();
|
||||
}
|
||||
|
||||
if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS)
|
||||
throw love::Exception("couldn't create vulkan instance");
|
||||
|
||||
volkLoadInstance(instance);
|
||||
}
|
||||
|
||||
bool Graphics::checkValidationSupport()
|
||||
{
|
||||
uint32_t layerCount;
|
||||
@@ -1458,7 +1456,6 @@ void Graphics::pickPhysicalDevice()
|
||||
minUniformBufferOffsetAlignment = properties.limits.minUniformBufferOffsetAlignment;
|
||||
deviceApiVersion = properties.apiVersion;
|
||||
|
||||
msaaSamples = getMsaaCount(requestedMsaa);
|
||||
depthStencilFormat = findDepthFormat();
|
||||
}
|
||||
|
||||
@@ -1573,7 +1570,7 @@ static void findOptionalDeviceExtensions(VkPhysicalDevice physicalDevice, Option
|
||||
optionalDeviceExtensions.memoryRequirements2 = true;
|
||||
if (strcmp(extension.extensionName, VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME) == 0)
|
||||
optionalDeviceExtensions.dedicatedAllocation = true;
|
||||
if (strcmp(extension.extensionName, VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME) == 0)
|
||||
if (strcmp(extension.extensionName, VK_EXT_MEMORY_BUDGET_EXTENSION_NAME) == 0)
|
||||
optionalDeviceExtensions.memoryBudget = true;
|
||||
if (strcmp(extension.extensionName, VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME) == 0)
|
||||
optionalDeviceExtensions.shaderFloatControls = true;
|
||||
@@ -2447,12 +2444,12 @@ void Graphics::setRenderPass(const RenderTargets &rts, int pixelw, int pixelh, b
|
||||
RenderPassConfiguration renderPassConfiguration{};
|
||||
for (const auto &color : rts.colors)
|
||||
renderPassConfiguration.colorAttachments.push_back({
|
||||
Vulkan::getTextureFormat(color.texture->getPixelFormat(), isPixelFormatSRGB(color.texture->getPixelFormat())).internalFormat,
|
||||
Vulkan::getTextureFormat(color.texture->getPixelFormat()).internalFormat,
|
||||
VK_ATTACHMENT_LOAD_OP_LOAD,
|
||||
dynamic_cast<Texture*>(color.texture)->getMsaaSamples() });
|
||||
if (rts.depthStencil.texture != nullptr)
|
||||
renderPassConfiguration.staticData.depthStencilAttachment = {
|
||||
Vulkan::getTextureFormat(rts.depthStencil.texture->getPixelFormat(), false).internalFormat,
|
||||
Vulkan::getTextureFormat(rts.depthStencil.texture->getPixelFormat()).internalFormat,
|
||||
VK_ATTACHMENT_LOAD_OP_LOAD,
|
||||
VK_ATTACHMENT_LOAD_OP_LOAD,
|
||||
dynamic_cast<Texture*>(rts.depthStencil.texture)->getMsaaSamples() };
|
||||
@@ -3040,8 +3037,6 @@ void Graphics::createDefaultTexture()
|
||||
|
||||
void Graphics::cleanup()
|
||||
{
|
||||
cleanupSwapChain();
|
||||
|
||||
for (auto &cleanUpFns : cleanUpFunctions)
|
||||
for (auto &cleanUpFn : cleanUpFns)
|
||||
cleanUpFn();
|
||||
@@ -3076,8 +3071,6 @@ void Graphics::cleanup()
|
||||
vkDestroyCommandPool(device, commandPool, nullptr);
|
||||
vkDestroyPipelineCache(device, pipelineCache, nullptr);
|
||||
vkDestroyDevice(device, nullptr);
|
||||
vkDestroySurfaceKHR(instance, surface, nullptr);
|
||||
vkDestroyInstance(instance, nullptr);
|
||||
}
|
||||
|
||||
void Graphics::cleanupSwapChain()
|
||||
@@ -3087,8 +3080,11 @@ void Graphics::cleanupSwapChain()
|
||||
vmaDestroyBuffer(vmaAllocator, readbackBuffer.buffer, readbackBuffer.allocation);
|
||||
vmaDestroyImage(vmaAllocator, readbackBuffer.image, readbackBuffer.imageAllocation);
|
||||
}
|
||||
vkDestroyImageView(device, colorImageView, nullptr);
|
||||
vmaDestroyImage(vmaAllocator, colorImage, colorImageAllocation);
|
||||
if (colorImage)
|
||||
{
|
||||
vkDestroyImageView(device, colorImageView, nullptr);
|
||||
vmaDestroyImage(vmaAllocator, colorImage, colorImageAllocation);
|
||||
}
|
||||
vkDestroyImageView(device, depthImageView, nullptr);
|
||||
vmaDestroyImage(vmaAllocator, depthImage, depthImageAllocation);
|
||||
for (const auto &swapChainImageView : swapChainImageViews)
|
||||
|
||||
@@ -256,6 +256,14 @@ struct ScreenshotReadbackBuffer
|
||||
VmaAllocation imageAllocation;
|
||||
};
|
||||
|
||||
enum SubmitMode
|
||||
{
|
||||
SUBMIT_PRESENT,
|
||||
SUBMIT_NOPRESENT,
|
||||
SUBMIT_RESTART,
|
||||
SUBMIT_MAXENUM,
|
||||
};
|
||||
|
||||
class Graphics final : public love::graphics::Graphics
|
||||
{
|
||||
public:
|
||||
@@ -289,8 +297,7 @@ public:
|
||||
void setBlendState(const BlendState &blend) override;
|
||||
void setPointSize(float size) override;
|
||||
void setWireframe(bool enable) override;
|
||||
PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const override;
|
||||
bool isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB) override;
|
||||
bool isPixelFormatSupported(PixelFormat format, uint32 usage) override;
|
||||
Renderer getRenderer() const override;
|
||||
bool usesGLSLES() const override;
|
||||
RendererInfo getRendererInfo() const override;
|
||||
@@ -300,12 +307,12 @@ public:
|
||||
|
||||
// internal functions.
|
||||
|
||||
const VkDevice getDevice() const;
|
||||
const VmaAllocator getVmaAllocator() const;
|
||||
VkDevice getDevice() const;
|
||||
VmaAllocator getVmaAllocator() const;
|
||||
VkCommandBuffer getCommandBufferForDataTransfer();
|
||||
void queueCleanUp(std::function<void()> cleanUp);
|
||||
void addReadbackCallback(std::function<void()> callback);
|
||||
void submitGpuCommands(bool present, void *screenshotCallbackData = nullptr);
|
||||
void submitGpuCommands(SubmitMode, void *screenshotCallbackData = nullptr);
|
||||
const VkDeviceSize getMinUniformBufferOffsetAlignment() const;
|
||||
VkSampler getCachedSampler(const SamplerState &sampler);
|
||||
void setComputeShader(Shader *computeShader);
|
||||
@@ -326,7 +333,6 @@ protected:
|
||||
void setRenderTargetsInternal(const RenderTargets &rts, int pixelw, int pixelh, bool hasSRGBtexture) override;
|
||||
|
||||
private:
|
||||
void createVulkanInstance();
|
||||
bool checkValidationSupport();
|
||||
void pickPhysicalDevice();
|
||||
int rateDeviceSuitability(VkPhysicalDevice device);
|
||||
|
||||
@@ -44,7 +44,7 @@ GraphicsReadback::GraphicsReadback(love::graphics::Graphics *gfx, ReadbackMethod
|
||||
|
||||
if (method == READBACK_IMMEDIATE)
|
||||
{
|
||||
vgfx->submitGpuCommands(false);
|
||||
vgfx->submitGpuCommands(SUBMIT_RESTART);
|
||||
if (stagingBuffer.get()) {
|
||||
status = readbackBuffer(stagingBuffer, 0, size);
|
||||
gfx->releaseTemporaryBuffer(stagingBuffer);
|
||||
@@ -79,7 +79,7 @@ GraphicsReadback::GraphicsReadback(love::graphics::Graphics *gfx, ReadbackMethod
|
||||
});
|
||||
|
||||
if (method == READBACK_IMMEDIATE)
|
||||
vgfx->submitGpuCommands(false);
|
||||
vgfx->submitGpuCommands(SUBMIT_RESTART);
|
||||
}
|
||||
|
||||
GraphicsReadback::~GraphicsReadback()
|
||||
@@ -89,7 +89,7 @@ GraphicsReadback::~GraphicsReadback()
|
||||
void GraphicsReadback::wait()
|
||||
{
|
||||
if (status == STATUS_WAITING)
|
||||
vgfx->submitGpuCommands(false);
|
||||
vgfx->submitGpuCommands(SUBMIT_RESTART);
|
||||
}
|
||||
|
||||
void GraphicsReadback::update()
|
||||
|
||||
@@ -551,7 +551,8 @@ int Shader::getVertexAttributeIndex(const std::string &name)
|
||||
|
||||
const Shader::UniformInfo *Shader::getUniformInfo(const std::string &name) const
|
||||
{
|
||||
return &uniformInfos.at(name);
|
||||
const auto it = uniformInfos.find(name);
|
||||
return it != uniformInfos.end() ? &(it->second) : nullptr;
|
||||
}
|
||||
|
||||
const Shader::UniformInfo *Shader::getUniformInfo(BuiltinUniform builtin) const
|
||||
@@ -656,6 +657,9 @@ void Shader::buildLocalUniforms(spirv_cross::Compiler &comp, const spirv_cross::
|
||||
if (reflectionIt != validationReflection.localUniforms.end())
|
||||
{
|
||||
const auto &localUniform = reflectionIt->second;
|
||||
if (localUniform.dataType == DATA_BASETYPE_BOOL)
|
||||
u.baseType = UNIFORM_BOOL;
|
||||
|
||||
const auto &values = localUniform.initializerValues;
|
||||
if (!values.empty())
|
||||
memcpy(
|
||||
|
||||
@@ -41,6 +41,10 @@ Texture::Texture(love::graphics::Graphics *gfx, const Settings &settings, const
|
||||
slices = *data;
|
||||
|
||||
loadVolatile();
|
||||
|
||||
// ImageData is referenced by the first loadVolatile call, but we don't
|
||||
// hang on to it after that so we can save memory.
|
||||
slices.clear();
|
||||
}
|
||||
|
||||
bool Texture::loadVolatile()
|
||||
@@ -55,7 +59,7 @@ bool Texture::loadVolatile()
|
||||
if (isPixelFormatColor(format))
|
||||
imageAspect |= VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
|
||||
auto vulkanFormat = Vulkan::getTextureFormat(format, sRGB);
|
||||
auto vulkanFormat = Vulkan::getTextureFormat(format);
|
||||
|
||||
VkImageUsageFlags usageFlags =
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
|
||||
@@ -150,7 +154,7 @@ bool Texture::loadVolatile()
|
||||
createTextureImageView();
|
||||
textureSampler = vgfx->getCachedSampler(samplerState);
|
||||
|
||||
if (!isPixelFormatDepthStencil(format) && mipmapCount > 1 && getMipmapsMode() != MIPMAPS_NONE)
|
||||
if (!isPixelFormatDepthStencil(format) && slices.getMipmapCount() <= 1 && getMipmapsMode() != MIPMAPS_NONE)
|
||||
generateMipmaps();
|
||||
|
||||
if (renderTarget)
|
||||
@@ -273,7 +277,7 @@ VkImageLayout Texture::getImageLayout() const
|
||||
|
||||
void Texture::createTextureImageView()
|
||||
{
|
||||
auto vulkanFormat = Vulkan::getTextureFormat(format, sRGB);
|
||||
auto vulkanFormat = Vulkan::getTextureFormat(format);
|
||||
|
||||
VkImageViewCreateInfo viewInfo{};
|
||||
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
@@ -345,7 +349,7 @@ void Texture::clear()
|
||||
|
||||
VkClearColorValue Texture::getClearValue()
|
||||
{
|
||||
auto vulkanFormat = Vulkan::getTextureFormat(format, sRGB);
|
||||
auto vulkanFormat = Vulkan::getTextureFormat(format);
|
||||
|
||||
VkClearColorValue clearColor{};
|
||||
switch (vulkanFormat.internalFormatRepresentation)
|
||||
|
||||
@@ -130,16 +130,10 @@ VkFormat Vulkan::getVulkanVertexFormat(DataFormat format)
|
||||
}
|
||||
}
|
||||
|
||||
TextureFormat Vulkan::getTextureFormat(PixelFormat format, bool sRGB)
|
||||
TextureFormat Vulkan::getTextureFormat(PixelFormat format)
|
||||
{
|
||||
TextureFormat textureFormat{};
|
||||
|
||||
if (sRGB)
|
||||
format = getSRGBPixelFormat(format);
|
||||
|
||||
if (!isPixelFormatCompressed(format) && !isPixelFormatSRGB(format))
|
||||
sRGB = false;
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case PIXELFORMAT_UNKNOWN:
|
||||
@@ -231,13 +225,13 @@ TextureFormat Vulkan::getTextureFormat(PixelFormat format, bool sRGB)
|
||||
case PIXELFORMAT_RGBA8_UNORM:
|
||||
textureFormat.internalFormat = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
break;
|
||||
case PIXELFORMAT_RGBA8_UNORM_sRGB:
|
||||
case PIXELFORMAT_RGBA8_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_R8G8B8A8_SRGB;
|
||||
break;
|
||||
case PIXELFORMAT_BGRA8_UNORM:
|
||||
textureFormat.internalFormat = VK_FORMAT_B8G8R8A8_UNORM;
|
||||
break;
|
||||
case PIXELFORMAT_BGRA8_UNORM_sRGB:
|
||||
case PIXELFORMAT_BGRA8_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_B8G8R8A8_SRGB;
|
||||
break;
|
||||
case PIXELFORMAT_RGBA8_INT:
|
||||
@@ -308,13 +302,22 @@ TextureFormat Vulkan::getTextureFormat(PixelFormat format, bool sRGB)
|
||||
textureFormat.internalFormat = VK_FORMAT_D32_SFLOAT_S8_UINT;
|
||||
break;
|
||||
case PIXELFORMAT_DXT1_UNORM:
|
||||
textureFormat.internalFormat = sRGB ? VK_FORMAT_BC1_RGBA_SRGB_BLOCK : VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
|
||||
textureFormat.internalFormat = VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_DXT1_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_BC1_RGBA_SRGB_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_DXT3_UNORM:
|
||||
textureFormat.internalFormat = sRGB ? VK_FORMAT_BC2_SRGB_BLOCK : VK_FORMAT_BC2_UNORM_BLOCK;
|
||||
textureFormat.internalFormat = VK_FORMAT_BC2_UNORM_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_DXT3_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_BC2_SRGB_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_DXT5_UNORM:
|
||||
textureFormat.internalFormat = sRGB ? VK_FORMAT_BC3_SRGB_BLOCK : VK_FORMAT_BC3_UNORM_BLOCK;
|
||||
textureFormat.internalFormat = VK_FORMAT_BC3_UNORM_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_DXT5_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_BC3_SRGB_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_BC4_UNORM:
|
||||
textureFormat.internalFormat = VK_FORMAT_BC4_UNORM_BLOCK;
|
||||
@@ -335,31 +338,55 @@ TextureFormat Vulkan::getTextureFormat(PixelFormat format, bool sRGB)
|
||||
textureFormat.internalFormat = VK_FORMAT_BC6H_SFLOAT_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_BC7_UNORM:
|
||||
textureFormat.internalFormat = sRGB ? VK_FORMAT_BC7_SRGB_BLOCK : VK_FORMAT_BC7_UNORM_BLOCK;
|
||||
textureFormat.internalFormat = VK_FORMAT_BC7_UNORM_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_BC7_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_BC7_SRGB_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_PVR1_RGB2_UNORM:
|
||||
textureFormat.internalFormat = sRGB ? VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG : VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG;
|
||||
textureFormat.internalFormat = VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG;
|
||||
break;
|
||||
case PIXELFORMAT_PVR1_RGB2_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG;
|
||||
break;
|
||||
case PIXELFORMAT_PVR1_RGB4_UNORM:
|
||||
textureFormat.internalFormat = sRGB ? VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG : VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG;
|
||||
textureFormat.internalFormat = VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG;
|
||||
break;
|
||||
case PIXELFORMAT_PVR1_RGB4_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG;
|
||||
break;
|
||||
case PIXELFORMAT_PVR1_RGBA2_UNORM:
|
||||
textureFormat.internalFormat = sRGB ? VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG : VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG;
|
||||
textureFormat.internalFormat = VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG;
|
||||
break;
|
||||
case PIXELFORMAT_PVR1_RGBA2_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG;
|
||||
break;
|
||||
case PIXELFORMAT_PVR1_RGBA4_UNORM:
|
||||
textureFormat.internalFormat = sRGB ? VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG : VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG;
|
||||
textureFormat.internalFormat = VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG;
|
||||
break;
|
||||
case PIXELFORMAT_PVR1_RGBA4_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG;
|
||||
break;
|
||||
case PIXELFORMAT_ETC1_UNORM:
|
||||
textureFormat.internalFormat = sRGB ? VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK : VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
|
||||
textureFormat.internalFormat = VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ETC2_RGB_UNORM:
|
||||
textureFormat.internalFormat = sRGB ? VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK : VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
|
||||
textureFormat.internalFormat = VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ETC2_RGB_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ETC2_RGBA_UNORM:
|
||||
textureFormat.internalFormat = sRGB ? VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK : VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
|
||||
textureFormat.internalFormat = VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ETC2_RGBA_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ETC2_RGBA1_UNORM:
|
||||
textureFormat.internalFormat = sRGB ? VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK : VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK;
|
||||
textureFormat.internalFormat = VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ETC2_RGBA1_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_EAC_R_UNORM:
|
||||
textureFormat.internalFormat = VK_FORMAT_EAC_R11_UNORM_BLOCK;
|
||||
@@ -373,47 +400,89 @@ TextureFormat Vulkan::getTextureFormat(PixelFormat format, bool sRGB)
|
||||
case PIXELFORMAT_EAC_RG_SNORM:
|
||||
textureFormat.internalFormat = VK_FORMAT_EAC_R11G11_SNORM_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_4x4:
|
||||
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_4x4_SRGB_BLOCK : VK_FORMAT_ASTC_4x4_UNORM_BLOCK;
|
||||
case PIXELFORMAT_ASTC_4x4_UNORM:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_4x4_UNORM_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_5x4:
|
||||
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_5x4_SRGB_BLOCK : VK_FORMAT_ASTC_5x4_UNORM_BLOCK;
|
||||
case PIXELFORMAT_ASTC_5x4_UNORM:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_5x4_UNORM_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_5x5:
|
||||
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_5x5_SRGB_BLOCK : VK_FORMAT_ASTC_5x5_UNORM_BLOCK;
|
||||
case PIXELFORMAT_ASTC_5x5_UNORM:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_5x5_UNORM_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_6x5:
|
||||
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_6x5_SRGB_BLOCK : VK_FORMAT_ASTC_6x5_UNORM_BLOCK;
|
||||
case PIXELFORMAT_ASTC_6x5_UNORM:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_6x5_UNORM_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_6x6:
|
||||
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_6x6_SRGB_BLOCK : VK_FORMAT_ASTC_6x6_UNORM_BLOCK;
|
||||
case PIXELFORMAT_ASTC_6x6_UNORM:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_6x6_UNORM_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_8x5:
|
||||
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_8x5_SRGB_BLOCK : VK_FORMAT_ASTC_8x5_UNORM_BLOCK;
|
||||
case PIXELFORMAT_ASTC_8x5_UNORM:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_8x5_UNORM_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_8x6:
|
||||
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_8x6_SRGB_BLOCK : VK_FORMAT_ASTC_8x6_UNORM_BLOCK;
|
||||
case PIXELFORMAT_ASTC_8x6_UNORM:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_8x6_UNORM_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_8x8:
|
||||
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_8x8_SRGB_BLOCK : VK_FORMAT_ASTC_8x8_UNORM_BLOCK;
|
||||
case PIXELFORMAT_ASTC_8x8_UNORM:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_8x8_UNORM_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x5:
|
||||
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_10x5_SRGB_BLOCK : VK_FORMAT_ASTC_10x5_UNORM_BLOCK;
|
||||
case PIXELFORMAT_ASTC_10x5_UNORM:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_10x5_UNORM_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x6:
|
||||
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_10x6_SRGB_BLOCK : VK_FORMAT_ASTC_10x6_UNORM_BLOCK;
|
||||
case PIXELFORMAT_ASTC_10x6_UNORM:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_10x6_UNORM_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x8:
|
||||
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_10x8_SRGB_BLOCK : VK_FORMAT_ASTC_10x8_UNORM_BLOCK;
|
||||
case PIXELFORMAT_ASTC_10x8_UNORM:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_10x8_UNORM_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x10:
|
||||
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_10x10_SRGB_BLOCK : VK_FORMAT_ASTC_10x10_UNORM_BLOCK;
|
||||
case PIXELFORMAT_ASTC_10x10_UNORM:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_10x10_UNORM_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_12x10:
|
||||
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_12x10_SRGB_BLOCK : VK_FORMAT_ASTC_12x10_UNORM_BLOCK;
|
||||
case PIXELFORMAT_ASTC_12x10_UNORM:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_12x10_UNORM_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_12x12:
|
||||
textureFormat.internalFormat = sRGB ? VK_FORMAT_ASTC_12x12_SRGB_BLOCK : VK_FORMAT_ASTC_12x12_UNORM_BLOCK;
|
||||
case PIXELFORMAT_ASTC_12x12_UNORM:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_12x12_UNORM_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_4x4_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_4x4_SRGB_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_5x4_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_5x4_SRGB_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_5x5_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_5x5_SRGB_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_6x5_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_6x5_SRGB_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_6x6_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_6x6_SRGB_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_8x5_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_8x5_SRGB_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_8x6_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_8x6_SRGB_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_8x8_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_8x8_SRGB_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x5_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_10x5_SRGB_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x6_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_10x6_SRGB_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x8_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_10x8_SRGB_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_10x10_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_10x10_SRGB_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_12x10_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_12x10_SRGB_BLOCK;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_12x12_sRGB:
|
||||
textureFormat.internalFormat = VK_FORMAT_ASTC_12x12_SRGB_BLOCK;
|
||||
break;
|
||||
default:
|
||||
throw love::Exception("unknown pixel format");
|
||||
|
||||
@@ -59,7 +59,7 @@ public:
|
||||
static void resetShaderSwitches();
|
||||
|
||||
static VkFormat getVulkanVertexFormat(DataFormat format);
|
||||
static TextureFormat getTextureFormat(PixelFormat, bool sRGB);
|
||||
static TextureFormat getTextureFormat(PixelFormat format);
|
||||
static std::string getVendorName(uint32_t vendorId);
|
||||
static std::string getVulkanApiVersion(uint32_t apiVersion);
|
||||
static VkPrimitiveTopology getPrimitiveTypeTopology(graphics::PrimitiveType);
|
||||
|
||||
@@ -2355,7 +2355,11 @@ int w_setColorMask(lua_State *L)
|
||||
{
|
||||
ColorChannelMask mask;
|
||||
|
||||
if (lua_gettop(L) <= 1)
|
||||
if (lua_isnoneornil(L, 1))
|
||||
{
|
||||
mask.r = mask.g = mask.b = mask.a = true;
|
||||
}
|
||||
else if (lua_gettop(L) <= 1)
|
||||
{
|
||||
// Set all color components if a single argument is given.
|
||||
mask.r = mask.g = mask.b = mask.a = luax_checkboolean(L, 1);
|
||||
@@ -2783,7 +2787,6 @@ int w_getTextureFormats(lua_State *L)
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
|
||||
bool rt = luax_checkboolflag(L, 1, Texture::getConstant(Texture::SETTING_RENDER_TARGET));
|
||||
bool linear = luax_boolflag(L, 1, Texture::getConstant(Texture::SETTING_LINEAR), false);
|
||||
bool computewrite = luax_boolflag(L, 1, Texture::getConstant(Texture::SETTING_COMPUTE_WRITE), false);
|
||||
|
||||
OptionalBool readable;
|
||||
@@ -2808,8 +2811,6 @@ int w_getTextureFormats(lua_State *L)
|
||||
if (rt && isPixelFormatDepth(format))
|
||||
continue;
|
||||
|
||||
bool sRGB = isGammaCorrect() && !linear;
|
||||
|
||||
uint32 usage = PIXELFORMATUSAGEFLAGS_NONE;
|
||||
if (rt)
|
||||
usage |= PIXELFORMATUSAGEFLAGS_RENDERTARGET;
|
||||
@@ -2818,7 +2819,7 @@ int w_getTextureFormats(lua_State *L)
|
||||
if (computewrite)
|
||||
usage |= PIXELFORMATUSAGEFLAGS_COMPUTEWRITE;
|
||||
|
||||
luax_pushboolean(L, instance()->isPixelFormatSupported(format, (PixelFormatUsageFlags) usage, sRGB));
|
||||
luax_pushboolean(L, instance()->isPixelFormatSupported(format, (PixelFormatUsageFlags) usage));
|
||||
lua_setfield(L, -2, name);
|
||||
}
|
||||
|
||||
@@ -2862,14 +2863,14 @@ int w_getCanvasFormats(lua_State *L)
|
||||
supported = [](PixelFormat format) -> bool
|
||||
{
|
||||
const uint32 usage = PIXELFORMATUSAGEFLAGS_SAMPLE | PIXELFORMATUSAGEFLAGS_RENDERTARGET;
|
||||
return instance()->isPixelFormatSupported(format, (PixelFormatUsageFlags) usage, false);
|
||||
return instance()->isPixelFormatSupported(format, (PixelFormatUsageFlags) usage);
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
supported = [](PixelFormat format) -> bool
|
||||
{
|
||||
return instance()->isPixelFormatSupported(format, PIXELFORMATUSAGEFLAGS_RENDERTARGET, false);
|
||||
return instance()->isPixelFormatSupported(format, PIXELFORMATUSAGEFLAGS_RENDERTARGET);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -2881,7 +2882,7 @@ int w_getCanvasFormats(lua_State *L)
|
||||
uint32 usage = PIXELFORMATUSAGEFLAGS_RENDERTARGET;
|
||||
if (readable)
|
||||
usage |= PIXELFORMATUSAGEFLAGS_SAMPLE;
|
||||
return instance()->isPixelFormatSupported(format, (PixelFormatUsageFlags) usage, false);
|
||||
return instance()->isPixelFormatSupported(format, (PixelFormatUsageFlags) usage);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2894,7 +2895,7 @@ int w_getImageFormats(lua_State *L)
|
||||
|
||||
const auto supported = [](PixelFormat format) -> bool
|
||||
{
|
||||
return instance()->isPixelFormatSupported(format, PIXELFORMATUSAGEFLAGS_SAMPLE, false);
|
||||
return instance()->isPixelFormatSupported(format, PIXELFORMATUSAGEFLAGS_SAMPLE);
|
||||
};
|
||||
|
||||
const auto ignore = [](PixelFormat format) -> bool
|
||||
|
||||
@@ -30,7 +30,6 @@ love::Type CompressedImageData::type("CompressedImageData", &Data::type);
|
||||
|
||||
CompressedImageData::CompressedImageData(const std::list<FormatHandler *> &formats, Data *filedata)
|
||||
: format(PIXELFORMAT_UNKNOWN)
|
||||
, sRGB(false)
|
||||
{
|
||||
FormatHandler *parser = nullptr;
|
||||
|
||||
@@ -46,7 +45,7 @@ CompressedImageData::CompressedImageData(const std::list<FormatHandler *> &forma
|
||||
if (parser == nullptr)
|
||||
throw love::Exception("Could not parse compressed data: Unknown format.");
|
||||
|
||||
memory = parser->parseCompressed(filedata, dataImages, format, sRGB);
|
||||
memory = parser->parseCompressed(filedata, dataImages, format);
|
||||
|
||||
if (memory == nullptr)
|
||||
throw love::Exception("Could not parse compressed data.");
|
||||
@@ -56,11 +55,14 @@ CompressedImageData::CompressedImageData(const std::list<FormatHandler *> &forma
|
||||
|
||||
if (dataImages.size() == 0 || memory->getSize() == 0)
|
||||
throw love::Exception("Could not parse compressed data: No valid data?");
|
||||
|
||||
// This throws away some information the decoder could give us, but we
|
||||
// can't really rely on it I think...
|
||||
format = getLinearPixelFormat(format);
|
||||
}
|
||||
|
||||
CompressedImageData::CompressedImageData(const CompressedImageData &c)
|
||||
: format(c.format)
|
||||
, sRGB(c.sRGB)
|
||||
{
|
||||
memory.set(c.memory->clone(), Acquire::NORETAIN);
|
||||
|
||||
@@ -134,9 +136,15 @@ PixelFormat CompressedImageData::getFormat() const
|
||||
return format;
|
||||
}
|
||||
|
||||
bool CompressedImageData::isSRGB() const
|
||||
void CompressedImageData::setLinear(bool linear)
|
||||
{
|
||||
return sRGB;
|
||||
for (auto &slice : dataImages)
|
||||
slice->setLinear(linear);
|
||||
}
|
||||
|
||||
bool CompressedImageData::isLinear() const
|
||||
{
|
||||
return dataImages.empty() ? false : dataImages[0]->isLinear();
|
||||
}
|
||||
|
||||
CompressedSlice *CompressedImageData::getSlice(int slice, int miplevel) const
|
||||
|
||||
@@ -93,14 +93,14 @@ public:
|
||||
**/
|
||||
PixelFormat getFormat() const;
|
||||
|
||||
bool isSRGB() const;
|
||||
void setLinear(bool linear);
|
||||
bool isLinear() const;
|
||||
|
||||
CompressedSlice *getSlice(int slice, int miplevel) const;
|
||||
|
||||
protected:
|
||||
|
||||
PixelFormat format;
|
||||
bool sRGB;
|
||||
|
||||
// Single block of memory containing all of the sub-images.
|
||||
StrongRef<ByteData> memory;
|
||||
|
||||
@@ -31,7 +31,6 @@ CompressedSlice::CompressedSlice(PixelFormat format, int width, int height, Byte
|
||||
, memory(memory)
|
||||
, offset(offset)
|
||||
, dataSize(size)
|
||||
, sRGB(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -40,7 +39,6 @@ CompressedSlice::CompressedSlice(const CompressedSlice &s)
|
||||
, memory(s.memory)
|
||||
, offset(s.offset)
|
||||
, dataSize(s.dataSize)
|
||||
, sRGB(s.sRGB)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,6 @@ public:
|
||||
CompressedSlice *clone() const override;
|
||||
void *getData() const override { return (uint8 *) memory->getData() + offset; }
|
||||
size_t getSize() const override { return dataSize; }
|
||||
bool isSRGB() const override { return sRGB; }
|
||||
size_t getOffset() const { return offset; }
|
||||
|
||||
private:
|
||||
@@ -54,7 +53,6 @@ private:
|
||||
StrongRef<ByteData> memory;
|
||||
size_t offset;
|
||||
size_t dataSize;
|
||||
bool sRGB;
|
||||
|
||||
}; // CompressedSlice
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ bool FormatHandler::canParseCompressed(Data* /*data*/)
|
||||
return false;
|
||||
}
|
||||
|
||||
StrongRef<ByteData> FormatHandler::parseCompressed(Data* /*filedata*/, std::vector<StrongRef<CompressedSlice>>& /*images*/, PixelFormat& /*format*/, bool& /*sRGB*/)
|
||||
StrongRef<ByteData> FormatHandler::parseCompressed(Data* /*filedata*/, std::vector<StrongRef<CompressedSlice>>& /*images*/, PixelFormat& /*format*/)
|
||||
{
|
||||
throw love::Exception("Compressed image parsing is not implemented for this format backend.");
|
||||
}
|
||||
|
||||
@@ -106,13 +106,12 @@ public:
|
||||
* @param[out] images The list of sub-images generated. Byte data is a
|
||||
* pointer to the returned data.
|
||||
* @param[out] format The format of the Compressed Data.
|
||||
* @param[out] sRGB Whether the texture is sRGB-encoded.
|
||||
*
|
||||
* @return The single block of memory containing the parsed images.
|
||||
**/
|
||||
virtual StrongRef<ByteData> parseCompressed(Data *filedata,
|
||||
std::vector<StrongRef<CompressedSlice>> &images,
|
||||
PixelFormat &format, bool &sRGB);
|
||||
PixelFormat &format);
|
||||
|
||||
/**
|
||||
* Frees raw pixel memory allocated by the format handler.
|
||||
|
||||
@@ -152,6 +152,10 @@ void ImageData::decode(Data *data)
|
||||
else
|
||||
delete[] this->data;
|
||||
|
||||
// This throws away some information the decoder could give us, but we
|
||||
// can't really rely on it I think...
|
||||
decodedimage.format = getLinearPixelFormat(decodedimage.format);
|
||||
|
||||
this->width = decodedimage.width;
|
||||
this->height = decodedimage.height;
|
||||
this->data = decodedimage.data;
|
||||
@@ -247,11 +251,6 @@ void *ImageData::getData() const
|
||||
return data;
|
||||
}
|
||||
|
||||
bool ImageData::isSRGB() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ImageData::inside(int x, int y) const
|
||||
{
|
||||
return x >= 0 && x < getWidth() && y >= 0 && y < getHeight();
|
||||
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
static love::Type type;
|
||||
|
||||
ImageData(Data *data);
|
||||
ImageData(int width, int height, PixelFormat format = PIXELFORMAT_RGBA8_UNORM);
|
||||
ImageData(int width, int height, PixelFormat format);
|
||||
ImageData(int width, int height, PixelFormat format, void *data, bool own);
|
||||
ImageData(const ImageData &c);
|
||||
virtual ~ImageData();
|
||||
@@ -116,7 +116,6 @@ public:
|
||||
ImageData *clone() const override;
|
||||
void *getData() const override;
|
||||
size_t getSize() const override;
|
||||
bool isSRGB() const override;
|
||||
|
||||
size_t getPixelSize() const;
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ ImageDataBase::ImageDataBase(PixelFormat format, int width, int height)
|
||||
: format(format)
|
||||
, width(width)
|
||||
, height(height)
|
||||
, linear(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -47,5 +48,15 @@ int ImageDataBase::getHeight() const
|
||||
return height;
|
||||
}
|
||||
|
||||
void ImageDataBase::setLinear(bool linear)
|
||||
{
|
||||
this->linear = linear;
|
||||
}
|
||||
|
||||
bool ImageDataBase::isLinear() const
|
||||
{
|
||||
return linear;
|
||||
}
|
||||
|
||||
} // image
|
||||
} // love
|
||||
|
||||
@@ -40,7 +40,8 @@ public:
|
||||
int getWidth() const;
|
||||
int getHeight() const;
|
||||
|
||||
virtual bool isSRGB() const = 0;
|
||||
void setLinear(bool linear);
|
||||
bool isLinear() const;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -50,6 +51,8 @@ protected:
|
||||
int width;
|
||||
int height;
|
||||
|
||||
bool linear;
|
||||
|
||||
}; // ImageDataBase
|
||||
|
||||
} // image
|
||||
|
||||
@@ -54,33 +54,33 @@ static PixelFormat convertFormat(uint32 blockX, uint32 blockY, uint32 blockZ)
|
||||
return PIXELFORMAT_UNKNOWN;
|
||||
|
||||
if (blockX == 4 && blockY == 4)
|
||||
return PIXELFORMAT_ASTC_4x4;
|
||||
return PIXELFORMAT_ASTC_4x4_UNORM;
|
||||
else if (blockX == 5 && blockY == 4)
|
||||
return PIXELFORMAT_ASTC_5x4;
|
||||
return PIXELFORMAT_ASTC_5x4_UNORM;
|
||||
else if (blockX == 5 && blockY == 5)
|
||||
return PIXELFORMAT_ASTC_5x5;
|
||||
return PIXELFORMAT_ASTC_5x5_UNORM;
|
||||
else if (blockX == 6 && blockY == 5)
|
||||
return PIXELFORMAT_ASTC_6x5;
|
||||
return PIXELFORMAT_ASTC_6x5_UNORM;
|
||||
else if (blockX == 6 && blockY == 6)
|
||||
return PIXELFORMAT_ASTC_6x6;
|
||||
return PIXELFORMAT_ASTC_6x6_UNORM;
|
||||
else if (blockX == 8 && blockY == 5)
|
||||
return PIXELFORMAT_ASTC_8x5;
|
||||
return PIXELFORMAT_ASTC_8x5_UNORM;
|
||||
else if (blockX == 8 && blockY == 6)
|
||||
return PIXELFORMAT_ASTC_8x6;
|
||||
return PIXELFORMAT_ASTC_8x6_UNORM;
|
||||
else if (blockX == 8 && blockY == 8)
|
||||
return PIXELFORMAT_ASTC_8x8;
|
||||
return PIXELFORMAT_ASTC_8x8_UNORM;
|
||||
else if (blockX == 10 && blockY == 5)
|
||||
return PIXELFORMAT_ASTC_10x5;
|
||||
return PIXELFORMAT_ASTC_10x5_UNORM;
|
||||
else if (blockX == 10 && blockY == 6)
|
||||
return PIXELFORMAT_ASTC_10x6;
|
||||
return PIXELFORMAT_ASTC_10x6_UNORM;
|
||||
else if (blockX == 10 && blockY == 8)
|
||||
return PIXELFORMAT_ASTC_10x8;
|
||||
return PIXELFORMAT_ASTC_10x8_UNORM;
|
||||
else if (blockX == 10 && blockY == 10)
|
||||
return PIXELFORMAT_ASTC_10x10;
|
||||
return PIXELFORMAT_ASTC_10x10_UNORM;
|
||||
else if (blockX == 12 && blockY == 10)
|
||||
return PIXELFORMAT_ASTC_12x10;
|
||||
return PIXELFORMAT_ASTC_12x10_UNORM;
|
||||
else if (blockX == 12 && blockY == 12)
|
||||
return PIXELFORMAT_ASTC_12x12;
|
||||
return PIXELFORMAT_ASTC_12x12_UNORM;
|
||||
|
||||
return PIXELFORMAT_UNKNOWN;
|
||||
}
|
||||
@@ -105,7 +105,7 @@ bool ASTCHandler::canParseCompressed(Data *data)
|
||||
return true;
|
||||
}
|
||||
|
||||
StrongRef<ByteData> ASTCHandler::parseCompressed(Data *filedata, std::vector<StrongRef<CompressedSlice>> &images, PixelFormat &format, bool &sRGB)
|
||||
StrongRef<ByteData> ASTCHandler::parseCompressed(Data *filedata, std::vector<StrongRef<CompressedSlice>> &images, PixelFormat &format)
|
||||
{
|
||||
if (!canParseCompressed(filedata))
|
||||
throw love::Exception("Could not decode compressed data (not an .astc file?)");
|
||||
@@ -138,8 +138,6 @@ StrongRef<ByteData> ASTCHandler::parseCompressed(Data *filedata, std::vector<Str
|
||||
images.emplace_back(new CompressedSlice(cformat, sizeX, sizeY, memory, 0, totalsize), Acquire::NORETAIN);
|
||||
|
||||
format = cformat;
|
||||
sRGB = false;
|
||||
|
||||
return memory;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
|
||||
StrongRef<ByteData> parseCompressed(Data *filedata,
|
||||
std::vector<StrongRef<CompressedSlice>> &images,
|
||||
PixelFormat &format, bool &sRGB) override;
|
||||
PixelFormat &format) override;
|
||||
|
||||
}; // ASTCHandler
|
||||
|
||||
|
||||
@@ -137,10 +137,8 @@ enum KTXGLInternalFormat
|
||||
KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR = 0x93DD
|
||||
};
|
||||
|
||||
PixelFormat convertFormat(uint32 glformat, bool &sRGB)
|
||||
PixelFormat convertFormat(uint32 glformat)
|
||||
{
|
||||
sRGB = false;
|
||||
|
||||
// hnnngg ASTC...
|
||||
|
||||
switch (glformat)
|
||||
@@ -160,18 +158,15 @@ PixelFormat convertFormat(uint32 glformat, bool &sRGB)
|
||||
case KTX_GL_COMPRESSED_RGB8_ETC2:
|
||||
return PIXELFORMAT_ETC2_RGB_UNORM;
|
||||
case KTX_GL_COMPRESSED_SRGB8_ETC2:
|
||||
sRGB = true;
|
||||
return PIXELFORMAT_ETC2_RGB_UNORM;
|
||||
return PIXELFORMAT_ETC2_RGB_sRGB;
|
||||
case KTX_GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
|
||||
return PIXELFORMAT_ETC2_RGBA1_UNORM;
|
||||
case KTX_GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
|
||||
sRGB = true;
|
||||
return PIXELFORMAT_ETC2_RGBA1_UNORM;
|
||||
return PIXELFORMAT_ETC2_RGBA1_sRGB;
|
||||
case KTX_GL_COMPRESSED_RGBA8_ETC2_EAC:
|
||||
return PIXELFORMAT_ETC2_RGBA_UNORM;
|
||||
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
|
||||
sRGB = true;
|
||||
return PIXELFORMAT_ETC2_RGBA_UNORM;
|
||||
return PIXELFORMAT_ETC2_RGBA_sRGB;
|
||||
|
||||
// PVRTC.
|
||||
case KTX_GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
|
||||
@@ -185,15 +180,15 @@ PixelFormat convertFormat(uint32 glformat, bool &sRGB)
|
||||
|
||||
// DXT.
|
||||
case KTX_GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
|
||||
sRGB = true;
|
||||
return PIXELFORMAT_DXT1_sRGB;
|
||||
case KTX_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
||||
return PIXELFORMAT_DXT1_UNORM;
|
||||
case KTX_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
|
||||
sRGB = true;
|
||||
return PIXELFORMAT_DXT3_sRGB;
|
||||
case KTX_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
||||
return PIXELFORMAT_DXT3_UNORM;
|
||||
case KTX_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
|
||||
sRGB = true;
|
||||
return PIXELFORMAT_DXT5_sRGB;
|
||||
case KTX_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||
return PIXELFORMAT_DXT5_UNORM;
|
||||
|
||||
@@ -209,7 +204,7 @@ PixelFormat convertFormat(uint32 glformat, bool &sRGB)
|
||||
|
||||
// BC6 and BC7.
|
||||
case KTX_GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
|
||||
sRGB = true;
|
||||
return PIXELFORMAT_BC7_sRGB;
|
||||
case KTX_GL_COMPRESSED_RGBA_BPTC_UNORM:
|
||||
return PIXELFORMAT_BC7_UNORM;
|
||||
case KTX_GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
|
||||
@@ -219,61 +214,61 @@ PixelFormat convertFormat(uint32 glformat, bool &sRGB)
|
||||
|
||||
// ASTC.
|
||||
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
|
||||
sRGB = true;
|
||||
return PIXELFORMAT_ASTC_4x4_sRGB;
|
||||
case KTX_GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
|
||||
return PIXELFORMAT_ASTC_4x4;
|
||||
return PIXELFORMAT_ASTC_4x4_UNORM;
|
||||
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
|
||||
sRGB = true;
|
||||
return PIXELFORMAT_ASTC_5x4_sRGB;
|
||||
case KTX_GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
|
||||
return PIXELFORMAT_ASTC_5x4;
|
||||
return PIXELFORMAT_ASTC_5x4_UNORM;
|
||||
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
|
||||
sRGB = true;
|
||||
return PIXELFORMAT_ASTC_5x5_sRGB;
|
||||
case KTX_GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
|
||||
return PIXELFORMAT_ASTC_5x5;
|
||||
return PIXELFORMAT_ASTC_5x5_UNORM;
|
||||
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
|
||||
sRGB = true;
|
||||
return PIXELFORMAT_ASTC_6x5_sRGB;
|
||||
case KTX_GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
|
||||
return PIXELFORMAT_ASTC_6x5;
|
||||
return PIXELFORMAT_ASTC_6x5_UNORM;
|
||||
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
|
||||
sRGB = true;
|
||||
return PIXELFORMAT_ASTC_6x6_sRGB;
|
||||
case KTX_GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
|
||||
return PIXELFORMAT_ASTC_6x6;
|
||||
return PIXELFORMAT_ASTC_6x6_UNORM;
|
||||
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
|
||||
sRGB = true;
|
||||
return PIXELFORMAT_ASTC_8x5_sRGB;
|
||||
case KTX_GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
|
||||
return PIXELFORMAT_ASTC_8x5;
|
||||
return PIXELFORMAT_ASTC_8x5_UNORM;
|
||||
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
|
||||
sRGB = true;
|
||||
return PIXELFORMAT_ASTC_8x6_sRGB;
|
||||
case KTX_GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
|
||||
return PIXELFORMAT_ASTC_8x6;
|
||||
return PIXELFORMAT_ASTC_8x6_UNORM;
|
||||
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
|
||||
sRGB = true;
|
||||
return PIXELFORMAT_ASTC_8x8_sRGB;
|
||||
case KTX_GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
|
||||
return PIXELFORMAT_ASTC_8x8;
|
||||
return PIXELFORMAT_ASTC_8x8_UNORM;
|
||||
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
|
||||
sRGB = true;
|
||||
return PIXELFORMAT_ASTC_10x5_sRGB;
|
||||
case KTX_GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
|
||||
return PIXELFORMAT_ASTC_10x5;
|
||||
return PIXELFORMAT_ASTC_10x5_UNORM;
|
||||
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
|
||||
sRGB = true;
|
||||
return PIXELFORMAT_ASTC_10x6_sRGB;
|
||||
case KTX_GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
|
||||
return PIXELFORMAT_ASTC_10x6;
|
||||
return PIXELFORMAT_ASTC_10x6_UNORM;
|
||||
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
|
||||
sRGB = true;
|
||||
return PIXELFORMAT_ASTC_10x8_sRGB;
|
||||
case KTX_GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
|
||||
return PIXELFORMAT_ASTC_10x8;
|
||||
return PIXELFORMAT_ASTC_10x8_UNORM;
|
||||
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
|
||||
sRGB = true;
|
||||
return PIXELFORMAT_ASTC_10x10_sRGB;
|
||||
case KTX_GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
|
||||
return PIXELFORMAT_ASTC_10x10;
|
||||
return PIXELFORMAT_ASTC_10x10_UNORM;
|
||||
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
|
||||
sRGB = true;
|
||||
return PIXELFORMAT_ASTC_12x10_sRGB;
|
||||
case KTX_GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
|
||||
return PIXELFORMAT_ASTC_12x10;
|
||||
return PIXELFORMAT_ASTC_12x10_UNORM;
|
||||
case KTX_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
|
||||
sRGB = true;
|
||||
return PIXELFORMAT_ASTC_12x12_sRGB;
|
||||
case KTX_GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
|
||||
return PIXELFORMAT_ASTC_12x12;
|
||||
return PIXELFORMAT_ASTC_12x12_UNORM;
|
||||
default:
|
||||
return PIXELFORMAT_UNKNOWN;
|
||||
}
|
||||
@@ -298,7 +293,7 @@ bool KTXHandler::canParseCompressed(Data *data)
|
||||
return true;
|
||||
}
|
||||
|
||||
StrongRef<ByteData> KTXHandler::parseCompressed(Data *filedata, std::vector<StrongRef<CompressedSlice>> &images, PixelFormat &format, bool &sRGB)
|
||||
StrongRef<ByteData> KTXHandler::parseCompressed(Data *filedata, std::vector<StrongRef<CompressedSlice>> &images, PixelFormat &format)
|
||||
{
|
||||
if (!canParseCompressed(filedata))
|
||||
throw love::Exception("Could not decode compressed data (not a KTX file?)");
|
||||
@@ -314,8 +309,7 @@ StrongRef<ByteData> KTXHandler::parseCompressed(Data *filedata, std::vector<Stro
|
||||
|
||||
header.numberOfMipmapLevels = std::max(header.numberOfMipmapLevels, 1u);
|
||||
|
||||
bool isSRGB = false;
|
||||
PixelFormat cformat = convertFormat(header.glInternalFormat, isSRGB);
|
||||
PixelFormat cformat = convertFormat(header.glInternalFormat);
|
||||
|
||||
if (cformat == PIXELFORMAT_UNKNOWN)
|
||||
throw love::Exception("Unsupported image format in KTX file.");
|
||||
@@ -386,8 +380,6 @@ StrongRef<ByteData> KTXHandler::parseCompressed(Data *filedata, std::vector<Stro
|
||||
}
|
||||
|
||||
format = cformat;
|
||||
sRGB = isSRGB;
|
||||
|
||||
return memory;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
|
||||
StrongRef<ByteData> parseCompressed(Data *filedata,
|
||||
std::vector<StrongRef<CompressedSlice>> &images,
|
||||
PixelFormat &format, bool &sRGB) override;
|
||||
PixelFormat &format) override;
|
||||
|
||||
}; // KTXHandler
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ bool PKMHandler::canParseCompressed(Data *data)
|
||||
return true;
|
||||
}
|
||||
|
||||
StrongRef<ByteData> PKMHandler::parseCompressed(Data *filedata, std::vector<StrongRef<CompressedSlice>> &images, PixelFormat &format, bool &sRGB)
|
||||
StrongRef<ByteData> PKMHandler::parseCompressed(Data *filedata, std::vector<StrongRef<CompressedSlice>> &images, PixelFormat &format)
|
||||
{
|
||||
if (!canParseCompressed(filedata))
|
||||
throw love::Exception("Could not decode compressed data (not a PKM file?)");
|
||||
@@ -148,8 +148,6 @@ StrongRef<ByteData> PKMHandler::parseCompressed(Data *filedata, std::vector<Stro
|
||||
images.emplace_back(new CompressedSlice(cformat, width, height, memory, 0, totalsize), Acquire::NORETAIN);
|
||||
|
||||
format = cformat;
|
||||
sRGB = false;
|
||||
|
||||
return memory;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
|
||||
StrongRef<ByteData> parseCompressed(Data *filedata,
|
||||
std::vector<StrongRef<CompressedSlice>> &images,
|
||||
PixelFormat &format, bool &sRGB) override;
|
||||
PixelFormat &format) override;
|
||||
|
||||
}; // PKMHandler
|
||||
|
||||
|
||||
@@ -256,33 +256,33 @@ static PixelFormat convertFormat(PVRV3PixelFormat format, PVRV3ChannelType chann
|
||||
case ePVRTPF_EAC_RG:
|
||||
return snorm ? PIXELFORMAT_EAC_RG_SNORM : PIXELFORMAT_EAC_RG_UNORM;
|
||||
case ePVRTPF_ASTC_4x4:
|
||||
return PIXELFORMAT_ASTC_4x4;
|
||||
return PIXELFORMAT_ASTC_4x4_UNORM;
|
||||
case ePVRTPF_ASTC_5x4:
|
||||
return PIXELFORMAT_ASTC_5x4;
|
||||
return PIXELFORMAT_ASTC_5x4_UNORM;
|
||||
case ePVRTPF_ASTC_5x5:
|
||||
return PIXELFORMAT_ASTC_5x5;
|
||||
return PIXELFORMAT_ASTC_5x5_UNORM;
|
||||
case ePVRTPF_ASTC_6x5:
|
||||
return PIXELFORMAT_ASTC_6x5;
|
||||
return PIXELFORMAT_ASTC_6x5_UNORM;
|
||||
case ePVRTPF_ASTC_6x6:
|
||||
return PIXELFORMAT_ASTC_6x6;
|
||||
return PIXELFORMAT_ASTC_6x6_UNORM;
|
||||
case ePVRTPF_ASTC_8x5:
|
||||
return PIXELFORMAT_ASTC_8x5;
|
||||
return PIXELFORMAT_ASTC_8x5_UNORM;
|
||||
case ePVRTPF_ASTC_8x6:
|
||||
return PIXELFORMAT_ASTC_8x6;
|
||||
return PIXELFORMAT_ASTC_8x6_UNORM;
|
||||
case ePVRTPF_ASTC_8x8:
|
||||
return PIXELFORMAT_ASTC_8x8;
|
||||
return PIXELFORMAT_ASTC_8x8_UNORM;
|
||||
case ePVRTPF_ASTC_10x5:
|
||||
return PIXELFORMAT_ASTC_10x5;
|
||||
return PIXELFORMAT_ASTC_10x5_UNORM;
|
||||
case ePVRTPF_ASTC_10x6:
|
||||
return PIXELFORMAT_ASTC_10x6;
|
||||
return PIXELFORMAT_ASTC_10x6_UNORM;
|
||||
case ePVRTPF_ASTC_10x8:
|
||||
return PIXELFORMAT_ASTC_10x8;
|
||||
return PIXELFORMAT_ASTC_10x8_UNORM;
|
||||
case ePVRTPF_ASTC_10x10:
|
||||
return PIXELFORMAT_ASTC_10x10;
|
||||
return PIXELFORMAT_ASTC_10x10_UNORM;
|
||||
case ePVRTPF_ASTC_12x10:
|
||||
return PIXELFORMAT_ASTC_12x10;
|
||||
return PIXELFORMAT_ASTC_12x10_UNORM;
|
||||
case ePVRTPF_ASTC_12x12:
|
||||
return PIXELFORMAT_ASTC_12x12;
|
||||
return PIXELFORMAT_ASTC_12x12_UNORM;
|
||||
default:
|
||||
return PIXELFORMAT_UNKNOWN;
|
||||
}
|
||||
@@ -475,7 +475,7 @@ bool PVRHandler::canParseCompressed(Data *data)
|
||||
return false;
|
||||
}
|
||||
|
||||
StrongRef<ByteData> PVRHandler::parseCompressed(Data *filedata, std::vector<StrongRef<CompressedSlice>> &images, PixelFormat &format, bool &sRGB)
|
||||
StrongRef<ByteData> PVRHandler::parseCompressed(Data *filedata, std::vector<StrongRef<CompressedSlice>> &images, PixelFormat &format)
|
||||
{
|
||||
if (!canParseCompressed(filedata))
|
||||
throw love::Exception("Could not decode compressed data (not a PVR file?)");
|
||||
@@ -510,6 +510,9 @@ StrongRef<ByteData> PVRHandler::parseCompressed(Data *filedata, std::vector<Stro
|
||||
|
||||
PixelFormat cformat = convertFormat(pixelformat, channeltype);
|
||||
|
||||
if (header3.colorSpace == 1)
|
||||
cformat = getSRGBPixelFormat(cformat);
|
||||
|
||||
if (cformat == PIXELFORMAT_UNKNOWN)
|
||||
throw love::Exception("Could not parse PVR file: unsupported image format.");
|
||||
|
||||
@@ -551,8 +554,6 @@ StrongRef<ByteData> PVRHandler::parseCompressed(Data *filedata, std::vector<Stro
|
||||
}
|
||||
|
||||
format = cformat;
|
||||
sRGB = (header3.colorSpace == 1);
|
||||
|
||||
return memory;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
|
||||
StrongRef<ByteData> parseCompressed(Data *filedata,
|
||||
std::vector<StrongRef<CompressedSlice>> &images,
|
||||
PixelFormat &format, bool &sRGB) override;
|
||||
PixelFormat &format) override;
|
||||
|
||||
}; // PVRHandler
|
||||
|
||||
|
||||
@@ -32,13 +32,10 @@ namespace image
|
||||
namespace magpie
|
||||
{
|
||||
|
||||
static PixelFormat convertFormat(dds::dxinfo::DXGIFormat dxformat, bool &sRGB, bool &bgra)
|
||||
static PixelFormat convertFormat(dds::dxinfo::DXGIFormat dxformat)
|
||||
{
|
||||
using namespace dds::dxinfo;
|
||||
|
||||
sRGB = false;
|
||||
bgra = false;
|
||||
|
||||
switch (dxformat)
|
||||
{
|
||||
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
|
||||
@@ -65,9 +62,9 @@ static PixelFormat convertFormat(dds::dxinfo::DXGIFormat dxformat, bool &sRGB, b
|
||||
|
||||
case DXGI_FORMAT_R8G8B8A8_TYPELESS:
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
|
||||
sRGB = (dxformat == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB);
|
||||
return PIXELFORMAT_RGBA8_UNORM;
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
|
||||
return PIXELFORMAT_RGBA8_sRGB;
|
||||
|
||||
case DXGI_FORMAT_R16G16_TYPELESS:
|
||||
case DXGI_FORMAT_R16G16_FLOAT:
|
||||
@@ -98,21 +95,21 @@ static PixelFormat convertFormat(dds::dxinfo::DXGIFormat dxformat, bool &sRGB, b
|
||||
|
||||
case DXGI_FORMAT_BC1_TYPELESS:
|
||||
case DXGI_FORMAT_BC1_UNORM:
|
||||
case DXGI_FORMAT_BC1_UNORM_SRGB:
|
||||
sRGB = (dxformat == DXGI_FORMAT_BC1_UNORM_SRGB);
|
||||
return PIXELFORMAT_DXT1_UNORM;
|
||||
case DXGI_FORMAT_BC1_UNORM_SRGB:
|
||||
return PIXELFORMAT_DXT1_sRGB;
|
||||
|
||||
case DXGI_FORMAT_BC2_TYPELESS:
|
||||
case DXGI_FORMAT_BC2_UNORM:
|
||||
case DXGI_FORMAT_BC2_UNORM_SRGB:
|
||||
sRGB = (dxformat == DXGI_FORMAT_BC2_UNORM_SRGB);
|
||||
return PIXELFORMAT_DXT3_UNORM;
|
||||
case DXGI_FORMAT_BC2_UNORM_SRGB:
|
||||
return PIXELFORMAT_DXT3_sRGB;
|
||||
|
||||
case DXGI_FORMAT_BC3_TYPELESS:
|
||||
case DXGI_FORMAT_BC3_UNORM:
|
||||
case DXGI_FORMAT_BC3_UNORM_SRGB:
|
||||
sRGB = (dxformat == DXGI_FORMAT_BC3_UNORM_SRGB);
|
||||
return PIXELFORMAT_DXT5_UNORM;
|
||||
case DXGI_FORMAT_BC3_UNORM_SRGB:
|
||||
return PIXELFORMAT_DXT5_sRGB;
|
||||
|
||||
case DXGI_FORMAT_BC4_TYPELESS:
|
||||
case DXGI_FORMAT_BC4_UNORM:
|
||||
@@ -136,10 +133,9 @@ static PixelFormat convertFormat(dds::dxinfo::DXGIFormat dxformat, bool &sRGB, b
|
||||
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM:
|
||||
case DXGI_FORMAT_B8G8R8A8_TYPELESS:
|
||||
return PIXELFORMAT_BGRA8_UNORM;
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
|
||||
sRGB = (dxformat == DXGI_FORMAT_B8G8R8A8_UNORM_SRGB);
|
||||
bgra = true;
|
||||
return PIXELFORMAT_RGBA8_UNORM;
|
||||
return PIXELFORMAT_BGRA8_sRGB;
|
||||
|
||||
case DXGI_FORMAT_BC6H_TYPELESS:
|
||||
case DXGI_FORMAT_BC6H_UF16:
|
||||
@@ -150,9 +146,9 @@ static PixelFormat convertFormat(dds::dxinfo::DXGIFormat dxformat, bool &sRGB, b
|
||||
|
||||
case DXGI_FORMAT_BC7_TYPELESS:
|
||||
case DXGI_FORMAT_BC7_UNORM:
|
||||
case DXGI_FORMAT_BC7_UNORM_SRGB:
|
||||
sRGB = (dxformat == DXGI_FORMAT_BC7_UNORM_SRGB);
|
||||
return PIXELFORMAT_BC7_UNORM;
|
||||
case DXGI_FORMAT_BC7_UNORM_SRGB:
|
||||
return PIXELFORMAT_BC7_sRGB;
|
||||
|
||||
default:
|
||||
return PIXELFORMAT_UNKNOWN;
|
||||
@@ -164,9 +160,13 @@ bool DDSHandler::canDecode(Data *data)
|
||||
using namespace dds::dxinfo;
|
||||
|
||||
DXGIFormat dxformat = dds::getDDSPixelFormat(data->getData(), data->getSize());
|
||||
bool isSRGB = false;
|
||||
bool bgra = false;
|
||||
PixelFormat format = convertFormat(dxformat, isSRGB, bgra);
|
||||
PixelFormat format = convertFormat(dxformat);
|
||||
|
||||
// We convert BGRA to RGBA
|
||||
if (format == PIXELFORMAT_BGRA8_UNORM)
|
||||
format = PIXELFORMAT_RGBA8_UNORM;
|
||||
else if (format == PIXELFORMAT_BGRA8_sRGB)
|
||||
format = PIXELFORMAT_RGBA8_sRGB;
|
||||
|
||||
return ImageData::validPixelFormat(format);
|
||||
}
|
||||
@@ -177,9 +177,19 @@ FormatHandler::DecodedImage DDSHandler::decode(Data *data)
|
||||
|
||||
dds::Parser parser(data->getData(), data->getSize());
|
||||
|
||||
bool isSRGB = false;
|
||||
img.format = convertFormat(parser.getFormat());
|
||||
|
||||
bool bgra = false;
|
||||
img.format = convertFormat(parser.getFormat(), isSRGB, bgra);
|
||||
if (img.format == PIXELFORMAT_BGRA8_UNORM)
|
||||
{
|
||||
img.format = PIXELFORMAT_RGBA8_UNORM;
|
||||
bgra = true;
|
||||
}
|
||||
else if (img.format == PIXELFORMAT_BGRA8_sRGB)
|
||||
{
|
||||
img.format = PIXELFORMAT_RGBA8_sRGB;
|
||||
bgra = true;
|
||||
}
|
||||
|
||||
if (!ImageData::validPixelFormat(img.format))
|
||||
throw love::Exception("Could not parse DDS pixel data: Unsupported format.");
|
||||
@@ -229,14 +239,12 @@ bool DDSHandler::canParseCompressed(Data *data)
|
||||
return dds::isCompressedDDS(data->getData(), data->getSize());
|
||||
}
|
||||
|
||||
StrongRef<ByteData> DDSHandler::parseCompressed(Data *filedata, std::vector<StrongRef<CompressedSlice>> &images, PixelFormat &format, bool &sRGB)
|
||||
StrongRef<ByteData> DDSHandler::parseCompressed(Data *filedata, std::vector<StrongRef<CompressedSlice>> &images, PixelFormat &format)
|
||||
{
|
||||
if (!dds::isCompressedDDS(filedata->getData(), filedata->getSize()))
|
||||
throw love::Exception("Could not decode compressed data (not a DDS file?)");
|
||||
|
||||
PixelFormat texformat = PIXELFORMAT_UNKNOWN;
|
||||
bool isSRGB = false;
|
||||
bool bgra = false;
|
||||
|
||||
size_t dataSize = 0;
|
||||
|
||||
@@ -245,7 +253,7 @@ StrongRef<ByteData> DDSHandler::parseCompressed(Data *filedata, std::vector<Stro
|
||||
// Attempt to parse the dds file.
|
||||
dds::Parser parser(filedata->getData(), filedata->getSize());
|
||||
|
||||
texformat = convertFormat(parser.getFormat(), isSRGB, bgra);
|
||||
texformat = convertFormat(parser.getFormat());
|
||||
|
||||
if (texformat == PIXELFORMAT_UNKNOWN)
|
||||
throw love::Exception("Could not parse compressed data: Unsupported format.");
|
||||
@@ -280,7 +288,6 @@ StrongRef<ByteData> DDSHandler::parseCompressed(Data *filedata, std::vector<Stro
|
||||
}
|
||||
|
||||
format = texformat;
|
||||
sRGB = isSRGB;
|
||||
return memory;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
bool canParseCompressed(Data *data) override;
|
||||
StrongRef<ByteData> parseCompressed(Data *filedata,
|
||||
std::vector<StrongRef<CompressedSlice>> &images,
|
||||
PixelFormat &format, bool &sRGB) override;
|
||||
PixelFormat &format) override;
|
||||
|
||||
}; // DDSHandler
|
||||
|
||||
|
||||
@@ -103,6 +103,20 @@ int w_CompressedImageData_getFormat(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_CompressedImageData_setLinear(lua_State *L)
|
||||
{
|
||||
CompressedImageData *t = luax_checkcompressedimagedata(L, 1);
|
||||
t->setLinear(luax_checkboolean(L, 2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_CompressedImageData_isLinear(lua_State *L)
|
||||
{
|
||||
CompressedImageData *t = luax_checkcompressedimagedata(L, 1);
|
||||
luax_pushboolean(L, t->isLinear());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg w_CompressedImageData_functions[] =
|
||||
{
|
||||
{ "clone", w_CompressedImageData_clone },
|
||||
@@ -111,6 +125,8 @@ static const luaL_Reg w_CompressedImageData_functions[] =
|
||||
{ "getDimensions", w_CompressedImageData_getDimensions },
|
||||
{ "getMipmapCount", w_CompressedImageData_getMipmapCount },
|
||||
{ "getFormat", w_CompressedImageData_getFormat },
|
||||
{ "setLinear", w_CompressedImageData_setLinear },
|
||||
{ "isLinear", w_CompressedImageData_isLinear },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
|
||||
@@ -66,6 +66,20 @@ int w_ImageData_getFormat(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_ImageData_setLinear(lua_State *L)
|
||||
{
|
||||
ImageData *t = luax_checkimagedata(L, 1);
|
||||
t->setLinear(luax_checkboolean(L, 2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_ImageData_isLinear(lua_State *L)
|
||||
{
|
||||
ImageData *t = luax_checkimagedata(L, 1);
|
||||
luax_pushboolean(L, t->isLinear());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_ImageData_getWidth(lua_State *L)
|
||||
{
|
||||
ImageData *t = luax_checkimagedata(L, 1);
|
||||
@@ -314,6 +328,8 @@ static const luaL_Reg w_ImageData_functions[] =
|
||||
{
|
||||
{ "clone", w_ImageData_clone },
|
||||
{ "getFormat", w_ImageData_getFormat },
|
||||
{ "setLinear", w_ImageData_setLinear },
|
||||
{ "isLinear", w_ImageData_isLinear },
|
||||
{ "getWidth", w_ImageData_getWidth },
|
||||
{ "getHeight", w_ImageData_getHeight },
|
||||
{ "getDimensions", w_ImageData_getDimensions },
|
||||
|
||||
@@ -23,12 +23,12 @@
|
||||
#include "common/math.h"
|
||||
|
||||
#include "Shape.h"
|
||||
#include "Fixture.h"
|
||||
#include "World.h"
|
||||
#include "Physics.h"
|
||||
|
||||
// Needed for luax_pushjoint.
|
||||
#include "wrap_Joint.h"
|
||||
#include "wrap_Shape.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
@@ -39,6 +39,7 @@ namespace box2d
|
||||
|
||||
Body::Body(World *world, b2Vec2 p, Body::Type type)
|
||||
: world(world)
|
||||
, hasCustomMass(false)
|
||||
{
|
||||
b2BodyDef def;
|
||||
def.position = Physics::scaleDown(p);
|
||||
@@ -249,6 +250,7 @@ void Body::setLinearDamping(float d)
|
||||
void Body::resetMassData()
|
||||
{
|
||||
body->ResetMassData();
|
||||
hasCustomMass = false;
|
||||
}
|
||||
|
||||
void Body::setMassData(float x, float y, float m, float i)
|
||||
@@ -258,6 +260,7 @@ void Body::setMassData(float x, float y, float m, float i)
|
||||
massData.mass = m;
|
||||
massData.I = Physics::scaleDown(Physics::scaleDown(i));
|
||||
body->SetMassData(&massData);
|
||||
hasCustomMass = true;
|
||||
}
|
||||
|
||||
void Body::setMass(float m)
|
||||
@@ -266,6 +269,7 @@ void Body::setMass(float m)
|
||||
body->GetMassData(&data);
|
||||
data.mass = m;
|
||||
body->SetMassData(&data);
|
||||
hasCustomMass = true;
|
||||
}
|
||||
|
||||
void Body::setInertia(float i)
|
||||
@@ -275,6 +279,7 @@ void Body::setInertia(float i)
|
||||
massData.mass = body->GetMass();
|
||||
massData.I = Physics::scaleDown(Physics::scaleDown(i));
|
||||
body->SetMassData(&massData);
|
||||
hasCustomMass = true;
|
||||
}
|
||||
|
||||
void Body::setGravityScale(float scale)
|
||||
@@ -461,7 +466,20 @@ World *Body::getWorld() const
|
||||
return world;
|
||||
}
|
||||
|
||||
int Body::getFixtures(lua_State *L) const
|
||||
Shape *Body::getShape() const
|
||||
{
|
||||
b2Fixture *f = body->GetFixtureList();
|
||||
if (f == nullptr)
|
||||
return nullptr;
|
||||
|
||||
Shape *shape = (Shape *)(f->GetUserData().pointer);
|
||||
if (!shape)
|
||||
throw love::Exception("A Shape has escaped Memoizer!");
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
int Body::getShapes(lua_State *L) const
|
||||
{
|
||||
lua_newtable(L);
|
||||
b2Fixture *f = body->GetFixtureList();
|
||||
@@ -470,10 +488,10 @@ int Body::getFixtures(lua_State *L) const
|
||||
{
|
||||
if (!f)
|
||||
break;
|
||||
Fixture *fixture = (Fixture *)(f->GetUserData().pointer);
|
||||
if (!fixture)
|
||||
throw love::Exception("A fixture has escaped Memoizer!");
|
||||
luax_pushtype(L, fixture);
|
||||
Shape *shape = (Shape *)(f->GetUserData().pointer);
|
||||
if (!shape)
|
||||
throw love::Exception("A Shape has escaped Memoizer!");
|
||||
luax_pushshape(L, shape);
|
||||
lua_rawseti(L, -2, i);
|
||||
i++;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@ namespace box2d
|
||||
// Forward declarations.
|
||||
class World;
|
||||
class Shape;
|
||||
class Fixture;
|
||||
|
||||
/**
|
||||
* A Body is an entity which has position and orientation
|
||||
@@ -57,7 +56,6 @@ public:
|
||||
friend class CircleShape;
|
||||
friend class PolygonShape;
|
||||
friend class Shape;
|
||||
friend class Fixture;
|
||||
|
||||
// Public because joints et al ask for b2body
|
||||
b2Body *body;
|
||||
@@ -139,6 +137,8 @@ public:
|
||||
**/
|
||||
int getMassData(lua_State *L);
|
||||
|
||||
bool hasCustomMassData() const { return hasCustomMass; }
|
||||
|
||||
/**
|
||||
* Gets the Body's angular damping.
|
||||
**/
|
||||
@@ -391,10 +391,14 @@ public:
|
||||
World *getWorld() const;
|
||||
|
||||
/**
|
||||
* Get an array of all the Fixtures attached to this Body.
|
||||
* @return An array of Fixtures.
|
||||
* Gets the first Shape attached to this Body.
|
||||
**/
|
||||
int getFixtures(lua_State *L) const;
|
||||
Shape *getShape() const;
|
||||
|
||||
/**
|
||||
* Get an array of all the Shapes attached to this Body.
|
||||
**/
|
||||
int getShapes(lua_State *L) const;
|
||||
|
||||
/**
|
||||
* Get an array of all Joints attached to this Body.
|
||||
@@ -431,6 +435,8 @@ private:
|
||||
// unowned?
|
||||
World *world;
|
||||
|
||||
bool hasCustomMass;
|
||||
|
||||
// Reference to arbitrary data.
|
||||
Reference* ref = nullptr;
|
||||
|
||||
|
||||
@@ -34,8 +34,8 @@ namespace box2d
|
||||
|
||||
love::Type ChainShape::type("ChainShape", &Shape::type);
|
||||
|
||||
ChainShape::ChainShape(b2ChainShape *c, bool own)
|
||||
: Shape(c, own)
|
||||
ChainShape::ChainShape(Body *body, const b2ChainShape &c)
|
||||
: Shape(body, c)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ ChainShape::~ChainShape()
|
||||
|
||||
void ChainShape::setNextVertex(float x, float y)
|
||||
{
|
||||
throwIfShapeNotValid();
|
||||
b2Vec2 v(x, y);
|
||||
b2ChainShape *c = (b2ChainShape *)shape;
|
||||
c->m_nextVertex = Physics::scaleDown(v);
|
||||
@@ -52,6 +53,7 @@ void ChainShape::setNextVertex(float x, float y)
|
||||
|
||||
void ChainShape::setPreviousVertex(float x, float y)
|
||||
{
|
||||
throwIfShapeNotValid();
|
||||
b2Vec2 v(x, y);
|
||||
b2ChainShape *c = (b2ChainShape *)shape;
|
||||
c->m_prevVertex = Physics::scaleDown(v);
|
||||
@@ -59,44 +61,40 @@ void ChainShape::setPreviousVertex(float x, float y)
|
||||
|
||||
b2Vec2 ChainShape::getNextVertex() const
|
||||
{
|
||||
throwIfShapeNotValid();
|
||||
b2ChainShape *c = (b2ChainShape *)shape;
|
||||
|
||||
return Physics::scaleUp(c->m_nextVertex);
|
||||
}
|
||||
|
||||
b2Vec2 ChainShape::getPreviousVertex() const
|
||||
{
|
||||
throwIfShapeNotValid();
|
||||
b2ChainShape *c = (b2ChainShape *)shape;
|
||||
|
||||
return Physics::scaleUp(c->m_prevVertex);
|
||||
}
|
||||
|
||||
EdgeShape *ChainShape::getChildEdge(int index) const
|
||||
{
|
||||
throwIfShapeNotValid();
|
||||
|
||||
b2ChainShape *c = (b2ChainShape *)shape;
|
||||
b2EdgeShape *e = new b2EdgeShape;
|
||||
|
||||
try
|
||||
{
|
||||
c->GetChildEdge(e, index);
|
||||
}
|
||||
catch (love::Exception &)
|
||||
{
|
||||
delete e;
|
||||
throw;
|
||||
}
|
||||
b2EdgeShape e;
|
||||
c->GetChildEdge(&e, index);
|
||||
|
||||
return new EdgeShape(e, true);
|
||||
return new EdgeShape(nullptr, e);
|
||||
}
|
||||
|
||||
int ChainShape::getVertexCount() const
|
||||
{
|
||||
throwIfShapeNotValid();
|
||||
b2ChainShape *c = (b2ChainShape *)shape;
|
||||
return c->m_count;
|
||||
}
|
||||
|
||||
b2Vec2 ChainShape::getPoint(int index) const
|
||||
{
|
||||
throwIfShapeNotValid();
|
||||
b2ChainShape *c = (b2ChainShape *)shape;
|
||||
if (index < 0 || index >= c->m_count)
|
||||
throw love::Exception("Physics error: index out of bounds");
|
||||
@@ -106,6 +104,7 @@ b2Vec2 ChainShape::getPoint(int index) const
|
||||
|
||||
const b2Vec2 *ChainShape::getPoints() const
|
||||
{
|
||||
throwIfShapeNotValid();
|
||||
b2ChainShape *c = (b2ChainShape *)shape;
|
||||
return c->m_vertices;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
* Create a new ChainShape from a Box2D chain shape.
|
||||
* @param c The chain shape.
|
||||
**/
|
||||
ChainShape(b2ChainShape *c, bool own = true);
|
||||
ChainShape(Body *body, const b2ChainShape &c);
|
||||
|
||||
virtual ~ChainShape();
|
||||
|
||||
|
||||
@@ -34,8 +34,8 @@ namespace box2d
|
||||
|
||||
love::Type CircleShape::type("CircleShape", &Shape::type);
|
||||
|
||||
CircleShape::CircleShape(b2CircleShape *c, bool own)
|
||||
: Shape(c, own)
|
||||
CircleShape::CircleShape(Body *body, const b2CircleShape &c)
|
||||
: Shape(body, c)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -45,16 +45,19 @@ CircleShape::~CircleShape()
|
||||
|
||||
float CircleShape::getRadius() const
|
||||
{
|
||||
throwIfShapeNotValid();
|
||||
return Physics::scaleUp(shape->m_radius);
|
||||
}
|
||||
|
||||
void CircleShape::setRadius(float r)
|
||||
{
|
||||
throwIfShapeNotValid();
|
||||
shape->m_radius = Physics::scaleDown(r);
|
||||
}
|
||||
|
||||
void CircleShape::getPoint(float &x_o, float &y_o) const
|
||||
{
|
||||
throwIfShapeNotValid();
|
||||
b2CircleShape *c = (b2CircleShape *) shape;
|
||||
x_o = Physics::scaleUp(c->m_p.x);
|
||||
y_o = Physics::scaleUp(c->m_p.y);
|
||||
@@ -62,6 +65,7 @@ void CircleShape::getPoint(float &x_o, float &y_o) const
|
||||
|
||||
void CircleShape::setPoint(float x, float y)
|
||||
{
|
||||
throwIfShapeNotValid();
|
||||
b2CircleShape *c = (b2CircleShape *) shape;
|
||||
c->m_p = Physics::scaleDown(b2Vec2(x, y));
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
* Create a new CircleShape from the a Box2D CircleShape definition.
|
||||
* @param c The CircleShape definition.
|
||||
**/
|
||||
CircleShape(b2CircleShape *c, bool own = true);
|
||||
CircleShape(Body *body, const b2CircleShape &c);
|
||||
|
||||
virtual ~CircleShape();
|
||||
|
||||
|
||||
@@ -35,7 +35,6 @@ Contact::Contact(World *world, b2Contact *contact)
|
||||
: contact(contact)
|
||||
, world(world)
|
||||
{
|
||||
//contact->user
|
||||
world->registerObject(contact, this);
|
||||
}
|
||||
|
||||
@@ -46,16 +45,16 @@ Contact::~Contact()
|
||||
|
||||
void Contact::invalidate()
|
||||
{
|
||||
if (contact != NULL)
|
||||
if (contact != nullptr)
|
||||
{
|
||||
world->unregisterObject(contact);
|
||||
contact = NULL;
|
||||
contact = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool Contact::isValid()
|
||||
{
|
||||
return contact != NULL;
|
||||
return contact != nullptr;
|
||||
}
|
||||
|
||||
int Contact::getPositions(lua_State *L)
|
||||
@@ -144,13 +143,13 @@ void Contact::getChildren(int &childA, int &childB)
|
||||
childB = contact->GetChildIndexB();
|
||||
}
|
||||
|
||||
void Contact::getFixtures(Fixture *&fixtureA, Fixture *&fixtureB)
|
||||
void Contact::getShapes(Shape *&shapeA, Shape *&shapeB)
|
||||
{
|
||||
fixtureA = (Fixture *) (contact->GetFixtureA()->GetUserData().pointer);
|
||||
fixtureB = (Fixture *) (contact->GetFixtureB()->GetUserData().pointer);
|
||||
shapeA = (Shape *) (contact->GetFixtureA()->GetUserData().pointer);
|
||||
shapeB = (Shape *) (contact->GetFixtureB()->GetUserData().pointer);
|
||||
|
||||
if (!fixtureA || !fixtureB)
|
||||
throw love::Exception("A fixture has escaped Memoizer!");
|
||||
if (!shapeA || !shapeB)
|
||||
throw love::Exception("A Shape has escaped Memoizer!");
|
||||
}
|
||||
|
||||
} // box2d
|
||||
|
||||
@@ -151,9 +151,9 @@ public:
|
||||
void getChildren(int &childA, int &childB);
|
||||
|
||||
/**
|
||||
* Gets the Fixtures associated with this Contact.
|
||||
* Gets the Shapes associated with this Contact.
|
||||
**/
|
||||
void getFixtures(Fixture *&fixtureA, Fixture *&fixtureB);
|
||||
void getShapes(Shape *&shapeA, Shape *&shapeB);
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -34,8 +34,8 @@ namespace box2d
|
||||
|
||||
love::Type EdgeShape::type("EdgeShape", &Shape::type);
|
||||
|
||||
EdgeShape::EdgeShape(b2EdgeShape *e, bool own)
|
||||
: Shape(e, own)
|
||||
EdgeShape::EdgeShape(Body *body, const b2EdgeShape &e)
|
||||
: Shape(body, e)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ EdgeShape::~EdgeShape()
|
||||
|
||||
void EdgeShape::setNextVertex(float x, float y)
|
||||
{
|
||||
throwIfShapeNotValid();
|
||||
b2EdgeShape *e = (b2EdgeShape *)shape;
|
||||
b2Vec2 v(x, y);
|
||||
e->m_vertex3 = Physics::scaleDown(v);
|
||||
@@ -52,13 +53,14 @@ void EdgeShape::setNextVertex(float x, float y)
|
||||
|
||||
b2Vec2 EdgeShape::getNextVertex() const
|
||||
{
|
||||
throwIfShapeNotValid();
|
||||
b2EdgeShape *e = (b2EdgeShape *)shape;
|
||||
|
||||
return Physics::scaleUp(e->m_vertex3);
|
||||
}
|
||||
|
||||
void EdgeShape::setPreviousVertex(float x, float y)
|
||||
{
|
||||
throwIfShapeNotValid();
|
||||
b2EdgeShape *e = (b2EdgeShape *)shape;
|
||||
b2Vec2 v(x, y);
|
||||
e->m_vertex0 = Physics::scaleDown(v);
|
||||
@@ -66,13 +68,14 @@ void EdgeShape::setPreviousVertex(float x, float y)
|
||||
|
||||
b2Vec2 EdgeShape::getPreviousVertex() const
|
||||
{
|
||||
throwIfShapeNotValid();
|
||||
b2EdgeShape *e = (b2EdgeShape *)shape;
|
||||
|
||||
return Physics::scaleUp(e->m_vertex0);
|
||||
}
|
||||
|
||||
int EdgeShape::getPoints(lua_State *L)
|
||||
{
|
||||
throwIfShapeNotValid();
|
||||
b2EdgeShape *e = (b2EdgeShape *)shape;
|
||||
b2Vec2 v1 = Physics::scaleUp(e->m_vertex1);
|
||||
b2Vec2 v2 = Physics::scaleUp(e->m_vertex2);
|
||||
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
* Create a new EdgeShape from a Box2D edge shape.
|
||||
* @param e The edge shape.
|
||||
**/
|
||||
EdgeShape(b2EdgeShape *e, bool own = true);
|
||||
EdgeShape(Body *body, const b2EdgeShape &e);
|
||||
|
||||
virtual ~EdgeShape();
|
||||
|
||||
|
||||
@@ -1,349 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2023 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 "Fixture.h"
|
||||
|
||||
// Module
|
||||
#include "Body.h"
|
||||
#include "World.h"
|
||||
#include "Physics.h"
|
||||
|
||||
// STD
|
||||
#include <bitset>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace physics
|
||||
{
|
||||
namespace box2d
|
||||
{
|
||||
|
||||
love::Type Fixture::type("Fixture", &Object::type);
|
||||
|
||||
Fixture::Fixture(Body *body, Shape *shape, float density)
|
||||
: body(body)
|
||||
, fixture(nullptr)
|
||||
{
|
||||
b2FixtureDef def;
|
||||
def.shape = shape->shape;
|
||||
def.userData.pointer = (uintptr_t)this;
|
||||
def.density = density;
|
||||
fixture = body->body->CreateFixture(&def);
|
||||
this->retain();
|
||||
}
|
||||
|
||||
Fixture::~Fixture()
|
||||
{
|
||||
if (ref)
|
||||
delete ref;
|
||||
}
|
||||
|
||||
void Fixture::checkCreateShape()
|
||||
{
|
||||
if (shape.get() != nullptr || fixture == nullptr || fixture->GetShape() == nullptr)
|
||||
return;
|
||||
|
||||
b2Shape *bshape = fixture->GetShape();
|
||||
|
||||
switch (bshape->GetType())
|
||||
{
|
||||
case b2Shape::e_circle:
|
||||
shape.set(new CircleShape((b2CircleShape *) bshape, false), Acquire::NORETAIN);
|
||||
break;
|
||||
case b2Shape::e_edge:
|
||||
shape.set(new EdgeShape((b2EdgeShape *) bshape, false), Acquire::NORETAIN);
|
||||
break;
|
||||
case b2Shape::e_polygon:
|
||||
shape.set(new PolygonShape((b2PolygonShape *) bshape, false), Acquire::NORETAIN);
|
||||
break;
|
||||
case b2Shape::e_chain:
|
||||
shape.set(new ChainShape((b2ChainShape *) bshape, false), Acquire::NORETAIN);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Shape::Type Fixture::getType()
|
||||
{
|
||||
checkCreateShape();
|
||||
if (shape.get() == nullptr)
|
||||
return Shape::SHAPE_INVALID;
|
||||
else
|
||||
return shape->getType();
|
||||
}
|
||||
|
||||
void Fixture::setFriction(float friction)
|
||||
{
|
||||
fixture->SetFriction(friction);
|
||||
}
|
||||
|
||||
void Fixture::setRestitution(float restitution)
|
||||
{
|
||||
fixture->SetRestitution(restitution);
|
||||
}
|
||||
|
||||
void Fixture::setDensity(float density)
|
||||
{
|
||||
fixture->SetDensity(density);
|
||||
}
|
||||
|
||||
void Fixture::setSensor(bool sensor)
|
||||
{
|
||||
fixture->SetSensor(sensor);
|
||||
}
|
||||
|
||||
float Fixture::getFriction() const
|
||||
{
|
||||
return fixture->GetFriction();
|
||||
}
|
||||
|
||||
float Fixture::getRestitution() const
|
||||
{
|
||||
return fixture->GetRestitution();
|
||||
}
|
||||
|
||||
float Fixture::getDensity() const
|
||||
{
|
||||
return fixture->GetDensity();
|
||||
}
|
||||
|
||||
bool Fixture::isSensor() const
|
||||
{
|
||||
return fixture->IsSensor();
|
||||
}
|
||||
|
||||
Body *Fixture::getBody() const
|
||||
{
|
||||
return body;
|
||||
}
|
||||
|
||||
Shape *Fixture::getShape()
|
||||
{
|
||||
checkCreateShape();
|
||||
return shape;
|
||||
}
|
||||
|
||||
bool Fixture::isValid() const
|
||||
{
|
||||
return fixture != nullptr;
|
||||
}
|
||||
|
||||
void Fixture::setFilterData(int *v)
|
||||
{
|
||||
b2Filter f;
|
||||
f.categoryBits = (uint16) v[0];
|
||||
f.maskBits = (uint16) v[1];
|
||||
f.groupIndex = (int16) v[2];
|
||||
fixture->SetFilterData(f);
|
||||
}
|
||||
|
||||
void Fixture::getFilterData(int *v)
|
||||
{
|
||||
b2Filter f = fixture->GetFilterData();
|
||||
v[0] = (int) f.categoryBits;
|
||||
v[1] = (int) f.maskBits;
|
||||
v[2] = (int) f.groupIndex;
|
||||
}
|
||||
|
||||
int Fixture::setCategory(lua_State *L)
|
||||
{
|
||||
b2Filter f = fixture->GetFilterData();
|
||||
f.categoryBits = (uint16)getBits(L);
|
||||
fixture->SetFilterData(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Fixture::setMask(lua_State *L)
|
||||
{
|
||||
b2Filter f = fixture->GetFilterData();
|
||||
f.maskBits = ~(uint16)getBits(L);
|
||||
fixture->SetFilterData(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Fixture::setGroupIndex(int index)
|
||||
{
|
||||
b2Filter f = fixture->GetFilterData();
|
||||
f.groupIndex = (uint16)index;
|
||||
fixture->SetFilterData(f);
|
||||
}
|
||||
|
||||
int Fixture::getGroupIndex() const
|
||||
{
|
||||
b2Filter f = fixture->GetFilterData();
|
||||
return f.groupIndex;
|
||||
}
|
||||
|
||||
int Fixture::getCategory(lua_State *L)
|
||||
{
|
||||
return pushBits(L, fixture->GetFilterData().categoryBits);
|
||||
}
|
||||
|
||||
int Fixture::getMask(lua_State *L)
|
||||
{
|
||||
return pushBits(L, ~(fixture->GetFilterData().maskBits));
|
||||
}
|
||||
|
||||
uint16 Fixture::getBits(lua_State *L)
|
||||
{
|
||||
// Get number of args.
|
||||
bool istable = lua_istable(L, 1);
|
||||
int argc = istable ? (int) luax_objlen(L, 1) : lua_gettop(L);
|
||||
|
||||
// The new bitset.
|
||||
std::bitset<16> b;
|
||||
|
||||
for (int i = 1; i <= argc; i++)
|
||||
{
|
||||
size_t bpos = 0;
|
||||
|
||||
if (istable)
|
||||
{
|
||||
lua_rawgeti(L, 1, i);
|
||||
bpos = (size_t) (lua_tointeger(L, -1) - 1);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
else
|
||||
bpos = (size_t) (lua_tointeger(L, i) - 1);
|
||||
|
||||
if (bpos >= 16)
|
||||
luaL_error(L, "Values must be in range 1-16.");
|
||||
|
||||
b.set(bpos, true);
|
||||
}
|
||||
|
||||
return (uint16)b.to_ulong();
|
||||
}
|
||||
|
||||
int Fixture::pushBits(lua_State *L, uint16 bits)
|
||||
{
|
||||
// Create a bitset.
|
||||
std::bitset<16> b((int)bits);
|
||||
|
||||
// Push all set bits.
|
||||
for (int i = 0; i<16; i++)
|
||||
if (b.test(i))
|
||||
lua_pushinteger(L, i+1);
|
||||
|
||||
// Count number of set bits.
|
||||
return (int)b.count();
|
||||
}
|
||||
|
||||
int Fixture::setUserData(lua_State *L)
|
||||
{
|
||||
love::luax_assert_argc(L, 1, 1);
|
||||
|
||||
if(!ref)
|
||||
ref = new Reference();
|
||||
|
||||
ref->ref(L);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Fixture::getUserData(lua_State *L)
|
||||
{
|
||||
if (ref != nullptr)
|
||||
ref->push(L);
|
||||
else
|
||||
lua_pushnil(L);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool Fixture::testPoint(float x, float y) const
|
||||
{
|
||||
return fixture->TestPoint(Physics::scaleDown(b2Vec2(x, y)));
|
||||
}
|
||||
|
||||
int Fixture::rayCast(lua_State *L) const
|
||||
{
|
||||
float p1x = Physics::scaleDown((float)luaL_checknumber(L, 1));
|
||||
float p1y = Physics::scaleDown((float)luaL_checknumber(L, 2));
|
||||
float p2x = Physics::scaleDown((float)luaL_checknumber(L, 3));
|
||||
float p2y = Physics::scaleDown((float)luaL_checknumber(L, 4));
|
||||
float maxFraction = (float)luaL_checknumber(L, 5);
|
||||
int childIndex = (int) luaL_optinteger(L, 6, 1) - 1; // Convert from 1-based index
|
||||
b2RayCastInput input;
|
||||
input.p1.Set(p1x, p1y);
|
||||
input.p2.Set(p2x, p2y);
|
||||
input.maxFraction = maxFraction;
|
||||
b2RayCastOutput output;
|
||||
if (!fixture->RayCast(&output, input, childIndex))
|
||||
return 0; // Nothing hit.
|
||||
lua_pushnumber(L, output.normal.x);
|
||||
lua_pushnumber(L, output.normal.y);
|
||||
lua_pushnumber(L, output.fraction);
|
||||
return 3;
|
||||
}
|
||||
|
||||
int Fixture::getBoundingBox(lua_State *L) const
|
||||
{
|
||||
int childIndex = (int) luaL_optinteger(L, 1, 1) - 1; // Convert from 1-based index
|
||||
b2AABB box;
|
||||
luax_catchexcept(L, [&]() { box = fixture->GetAABB(childIndex); });
|
||||
box = Physics::scaleUp(box);
|
||||
lua_pushnumber(L, box.lowerBound.x);
|
||||
lua_pushnumber(L, box.lowerBound.y);
|
||||
lua_pushnumber(L, box.upperBound.x);
|
||||
lua_pushnumber(L, box.upperBound.y);
|
||||
return 4;
|
||||
}
|
||||
|
||||
int Fixture::getMassData(lua_State *L) const
|
||||
{
|
||||
b2MassData data;
|
||||
fixture->GetMassData(&data);
|
||||
b2Vec2 center = Physics::scaleUp(data.center);
|
||||
lua_pushnumber(L, center.x);
|
||||
lua_pushnumber(L, center.y);
|
||||
lua_pushnumber(L, data.mass);
|
||||
lua_pushnumber(L, data.I);
|
||||
return 4;
|
||||
}
|
||||
|
||||
void Fixture::destroy(bool implicit)
|
||||
{
|
||||
if (body->world->world->IsLocked())
|
||||
{
|
||||
// Called during time step. Save reference for destruction afterwards.
|
||||
this->retain();
|
||||
body->world->destructFixtures.push_back(this);
|
||||
return;
|
||||
}
|
||||
|
||||
shape.set(nullptr);
|
||||
|
||||
if (!implicit && fixture != nullptr)
|
||||
body->body->DestroyFixture(fixture);
|
||||
fixture = nullptr;
|
||||
|
||||
// Remove userdata reference to avoid it sticking around after GC
|
||||
if (ref)
|
||||
ref->unref();
|
||||
|
||||
// Box2D fixture destroyed. Release its reference to the love Fixture.
|
||||
this->release();
|
||||
}
|
||||
|
||||
} // box2d
|
||||
} // physics
|
||||
} // love
|
||||
@@ -1,216 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2023 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.
|
||||
**/
|
||||
|
||||
#ifndef LOVE_PHYSICS_BOX2D_FIXTURE_H
|
||||
#define LOVE_PHYSICS_BOX2D_FIXTURE_H
|
||||
|
||||
// LOVE
|
||||
#include "physics/Shape.h"
|
||||
#include "physics/box2d/Body.h"
|
||||
#include "physics/box2d/Shape.h"
|
||||
#include "common/Object.h"
|
||||
#include "common/Reference.h"
|
||||
|
||||
// Box2D
|
||||
#include <box2d/Box2D.h>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace physics
|
||||
{
|
||||
namespace box2d
|
||||
{
|
||||
|
||||
class World;
|
||||
|
||||
/**
|
||||
* A Fixture is used to attach a shape to a body for collision detection.
|
||||
* A Fixture inherits its transform from its parent. Fixtures hold
|
||||
* additional non-geometric data such as friction, collision filters,
|
||||
* etc.
|
||||
**/
|
||||
class Fixture : public Object
|
||||
{
|
||||
public:
|
||||
friend class Physics;
|
||||
|
||||
static love::Type type;
|
||||
|
||||
/**
|
||||
* Creates a Fixture.
|
||||
**/
|
||||
Fixture(Body *body, Shape *shape, float density);
|
||||
|
||||
virtual ~Fixture();
|
||||
|
||||
/**
|
||||
* Gets the type of the Fixture's Shape. Useful for
|
||||
* debug drawing.
|
||||
**/
|
||||
Shape::Type getType();
|
||||
|
||||
/**
|
||||
* Gets the Shape attached to this Fixture.
|
||||
**/
|
||||
Shape *getShape();
|
||||
|
||||
/**
|
||||
* Returns true if the fixture is active in a Box2D world.
|
||||
**/
|
||||
bool isValid() const;
|
||||
|
||||
/**
|
||||
* Checks whether this Fixture acts as a sensor.
|
||||
* @return True if sensor, false otherwise.
|
||||
**/
|
||||
bool isSensor() const;
|
||||
|
||||
/**
|
||||
* Set whether this Fixture should be a sensor or not.
|
||||
* @param sensor True if sensor, false if not.
|
||||
**/
|
||||
void setSensor(bool sensor);
|
||||
|
||||
/**
|
||||
* Gets the Body this Fixture is attached to.
|
||||
**/
|
||||
Body *getBody() const;
|
||||
|
||||
/**
|
||||
* Sets the filter data. An integer array is used even though the
|
||||
* first two elements are unsigned shorts. The elements are:
|
||||
* category (16-bits), mask (16-bits) and group (32-bits/int).
|
||||
**/
|
||||
void setFilterData(int *v);
|
||||
|
||||
/**
|
||||
* Gets the filter data. An integer array is used even though the
|
||||
* first two elements are unsigned shorts. The elements are:
|
||||
* category (16-bits), mask (16-bits) and group (32-bits/int).
|
||||
**/
|
||||
void getFilterData(int *v);
|
||||
|
||||
/**
|
||||
* This function stores an in-C reference to
|
||||
* arbitrary Lua data in the Box2D Fixture object.
|
||||
**/
|
||||
int setUserData(lua_State *L);
|
||||
|
||||
/**
|
||||
* Gets the data set with setData. If no
|
||||
* data is set, nil is returned.
|
||||
**/
|
||||
int getUserData(lua_State *L);
|
||||
|
||||
/**
|
||||
* Sets the friction of the Fixture.
|
||||
* @param friction The new friction.
|
||||
**/
|
||||
void setFriction(float friction);
|
||||
|
||||
/**
|
||||
* Sets the restitution for the Fixture.
|
||||
* @param restitution The restitution.
|
||||
**/
|
||||
void setRestitution(float restitution);
|
||||
|
||||
/**
|
||||
* Sets the density of the Fixture.
|
||||
* @param density The density of the Fixture.
|
||||
**/
|
||||
void setDensity(float density);
|
||||
|
||||
/**
|
||||
* Gets the friction of the Fixture.
|
||||
* @returns The friction.
|
||||
**/
|
||||
float getFriction() const;
|
||||
|
||||
/**
|
||||
* Gets the restitution of the Fixture.
|
||||
* @return The restitution of the Fixture.
|
||||
**/
|
||||
float getRestitution() const;
|
||||
|
||||
/**
|
||||
* Gets the density of the Fixture.
|
||||
* @return The density.
|
||||
**/
|
||||
float getDensity() const;
|
||||
|
||||
/**
|
||||
* Checks if a point is inside the Fixture.
|
||||
* @param x The x-component of the point.
|
||||
* @param y The y-component of the point.
|
||||
**/
|
||||
bool testPoint(float x, float y) const;
|
||||
|
||||
/**
|
||||
* Cast a ray against this Fixture.
|
||||
**/
|
||||
int rayCast(lua_State *L) const;
|
||||
|
||||
void setGroupIndex(int index);
|
||||
int getGroupIndex() const;
|
||||
|
||||
int setCategory(lua_State *L);
|
||||
int setMask(lua_State *L);
|
||||
int getCategory(lua_State *L);
|
||||
int getMask(lua_State *L);
|
||||
uint16 getBits(lua_State *L);
|
||||
int pushBits(lua_State *L, uint16 bits);
|
||||
|
||||
/**
|
||||
* Gets the bounding box for this Fixture.
|
||||
* The function returns eight values which can be
|
||||
* passed directly to love.graphics.polygon.
|
||||
**/
|
||||
int getBoundingBox(lua_State *L) const;
|
||||
|
||||
/**
|
||||
* Gets the mass data for this Fixture.
|
||||
* This operation may be expensive.
|
||||
**/
|
||||
int getMassData(lua_State *L) const;
|
||||
|
||||
/**
|
||||
* Destroys this fixture.
|
||||
**/
|
||||
void destroy(bool implicit = false);
|
||||
|
||||
protected:
|
||||
|
||||
void checkCreateShape();
|
||||
|
||||
Body *body;
|
||||
b2Fixture *fixture;
|
||||
|
||||
// Reference to arbitrary data.
|
||||
Reference* ref = nullptr;
|
||||
|
||||
StrongRef<Shape> shape;
|
||||
|
||||
};
|
||||
|
||||
} // box2d
|
||||
} // physics
|
||||
} // love
|
||||
|
||||
#endif // LOVE_PHYSICS_BOX2D_FIXTURE_H
|
||||
@@ -35,6 +35,7 @@ namespace box2d
|
||||
float Physics::meter = Physics::DEFAULT_METER;
|
||||
|
||||
Physics::Physics()
|
||||
: blockAllocator()
|
||||
{
|
||||
meter = DEFAULT_METER;
|
||||
}
|
||||
@@ -63,173 +64,164 @@ Body *Physics::newBody(World *world, Body::Type type)
|
||||
return new Body(world, b2Vec2(0, 0), type);
|
||||
}
|
||||
|
||||
CircleShape *Physics::newCircleShape(float radius)
|
||||
Body *Physics::newCircleBody(World *world, Body::Type type, float x, float y, float radius)
|
||||
{
|
||||
return newCircleShape(0, 0, radius);
|
||||
StrongRef<Body> body(newBody(world, x, y, type), Acquire::NORETAIN);
|
||||
StrongRef<CircleShape> shape(newCircleShape(body, 0, 0, radius), Acquire::NORETAIN);
|
||||
body->retain();
|
||||
return body.get();
|
||||
}
|
||||
|
||||
CircleShape *Physics::newCircleShape(float x, float y, float radius)
|
||||
Body *Physics::newRectangleBody(World *world, Body::Type type, float x, float y, float w, float h, float angle)
|
||||
{
|
||||
b2CircleShape *s = new b2CircleShape();
|
||||
s->m_p = Physics::scaleDown(b2Vec2(x, y));
|
||||
s->m_radius = Physics::scaleDown(radius);
|
||||
return new CircleShape(s);
|
||||
StrongRef<Body> body(newBody(world, x, y, type), Acquire::NORETAIN);
|
||||
StrongRef<PolygonShape> shape(newRectangleShape(body, 0, 0, w, h, angle), Acquire::NORETAIN);
|
||||
body->retain();
|
||||
return body.get();
|
||||
}
|
||||
|
||||
PolygonShape *Physics::newRectangleShape(float w, float h)
|
||||
Body *Physics::newPolygonBody(World *world, Body::Type type, const Vector2 *coords, int count)
|
||||
{
|
||||
return newRectangleShape(0, 0, w, h, 0);
|
||||
Vector2 origin(0, 0);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
origin += coords[i] / count;
|
||||
|
||||
std::vector<Vector2> localcoords;
|
||||
for (int i = 0; i < count; i++)
|
||||
localcoords.push_back(coords[i] - origin);
|
||||
|
||||
StrongRef<Body> body(newBody(world, origin.x, origin.y, type), Acquire::NORETAIN);
|
||||
StrongRef<PolygonShape> shape(newPolygonShape(body, localcoords.data(), count), Acquire::NORETAIN);
|
||||
body->retain();
|
||||
return body.get();
|
||||
}
|
||||
|
||||
PolygonShape *Physics::newRectangleShape(float x, float y, float w, float h)
|
||||
Body *Physics::newEdgeBody(World *world, Body::Type type, float x1, float y1, float x2, float y2, bool oneSided)
|
||||
{
|
||||
return newRectangleShape(x, y, w, h, 0);
|
||||
float wx = (x2 - x1) / 2.0f;
|
||||
float wy = (y2 - y1) / 2.0f;
|
||||
StrongRef<Body> body(newBody(world, wx, wy, type), Acquire::NORETAIN);
|
||||
StrongRef<EdgeShape> shape(newEdgeShape(body, x1 - wx, y1 - wy, x2 - wx, y2 - wy, oneSided), Acquire::NORETAIN);
|
||||
body->retain();
|
||||
return body.get();
|
||||
}
|
||||
|
||||
PolygonShape *Physics::newRectangleShape(float x, float y, float w, float h, float angle)
|
||||
Body *Physics::newChainBody(World *world, Body::Type type, bool loop, const Vector2 *coords, int count)
|
||||
{
|
||||
b2PolygonShape *s = new b2PolygonShape();
|
||||
s->SetAsBox(Physics::scaleDown(w/2.0f), Physics::scaleDown(h/2.0f), Physics::scaleDown(b2Vec2(x, y)), angle);
|
||||
return new PolygonShape(s);
|
||||
Vector2 origin(0, 0);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
origin += coords[i] / count;
|
||||
|
||||
std::vector<Vector2> localcoords;
|
||||
for (int i = 0; i < count; i++)
|
||||
localcoords.push_back(coords[i] - origin);
|
||||
|
||||
StrongRef<Body> body(newBody(world, origin.x, origin.y, type), Acquire::NORETAIN);
|
||||
StrongRef<ChainShape> shape(newChainShape(body, loop, localcoords.data(), count), Acquire::NORETAIN);
|
||||
body->retain();
|
||||
return body.get();
|
||||
}
|
||||
|
||||
EdgeShape *Physics::newEdgeShape(float x1, float y1, float x2, float y2, bool oneSided)
|
||||
Shape *Physics::newAttachedShape(Body *body, Shape *prototype, float density)
|
||||
{
|
||||
b2EdgeShape *s = new b2EdgeShape();
|
||||
if (prototype->isValid())
|
||||
throw love::Exception("The given Shape must not be part of the World.");
|
||||
|
||||
Shape *shape = nullptr;
|
||||
|
||||
switch (prototype->getType())
|
||||
{
|
||||
case Shape::SHAPE_CIRCLE:
|
||||
shape = new CircleShape(body, *(b2CircleShape *) prototype->shape);
|
||||
break;
|
||||
case Shape::SHAPE_POLYGON:
|
||||
shape = new PolygonShape(body, *(b2PolygonShape *) prototype->shape);
|
||||
break;
|
||||
case Shape::SHAPE_EDGE:
|
||||
shape = new EdgeShape(body, *(b2EdgeShape *) prototype->shape);
|
||||
break;
|
||||
case Shape::SHAPE_CHAIN:
|
||||
shape = new ChainShape(body, *(b2ChainShape *) prototype->shape);
|
||||
break;
|
||||
default:
|
||||
throw love::Exception("Unknown shape type.");
|
||||
break;
|
||||
}
|
||||
|
||||
shape->setDensity(density);
|
||||
body->resetMassData();
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
CircleShape *Physics::newCircleShape(Body *body, float x, float y, float radius)
|
||||
{
|
||||
b2CircleShape s;
|
||||
s.m_p = Physics::scaleDown(b2Vec2(x, y));
|
||||
s.m_radius = Physics::scaleDown(radius);
|
||||
return new CircleShape(body, s);
|
||||
}
|
||||
|
||||
PolygonShape *Physics::newRectangleShape(Body *body, float x, float y, float w, float h, float angle)
|
||||
{
|
||||
b2PolygonShape s;
|
||||
s.SetAsBox(Physics::scaleDown(w/2.0f), Physics::scaleDown(h/2.0f), Physics::scaleDown(b2Vec2(x, y)), angle);
|
||||
return new PolygonShape(body, s);
|
||||
}
|
||||
|
||||
EdgeShape *Physics::newEdgeShape(Body *body, float x1, float y1, float x2, float y2, bool oneSided)
|
||||
{
|
||||
b2EdgeShape s;
|
||||
if (oneSided)
|
||||
{
|
||||
b2Vec2 v1 = Physics::scaleDown(b2Vec2(x1, y1));
|
||||
b2Vec2 v2 = Physics::scaleDown(b2Vec2(x2, y2));
|
||||
s->SetOneSided(v1, v1, v2, v2);
|
||||
s.SetOneSided(v1, v1, v2, v2);
|
||||
}
|
||||
else
|
||||
{
|
||||
s->SetTwoSided(Physics::scaleDown(b2Vec2(x1, y1)), Physics::scaleDown(b2Vec2(x2, y2)));
|
||||
s.SetTwoSided(Physics::scaleDown(b2Vec2(x1, y1)), Physics::scaleDown(b2Vec2(x2, y2)));
|
||||
}
|
||||
return new EdgeShape(s);
|
||||
return new EdgeShape(body, s);
|
||||
}
|
||||
|
||||
int Physics::newPolygonShape(lua_State *L)
|
||||
PolygonShape *Physics::newPolygonShape(Body *body, const Vector2 *coords, int count)
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
|
||||
bool istable = lua_istable(L, 1);
|
||||
|
||||
if (istable)
|
||||
argc = (int) luax_objlen(L, 1);
|
||||
|
||||
if (argc % 2 != 0)
|
||||
return luaL_error(L, "Number of vertex components must be a multiple of two.");
|
||||
|
||||
// 3 to 8 (b2_maxPolygonVertices) vertices
|
||||
int vcount = argc / 2;
|
||||
if (vcount < 3)
|
||||
return luaL_error(L, "Expected a minimum of 3 vertices, got %d.", vcount);
|
||||
else if (vcount > b2_maxPolygonVertices)
|
||||
return luaL_error(L, "Expected a maximum of %d vertices, got %d.", b2_maxPolygonVertices, vcount);
|
||||
if (count < 3)
|
||||
throw love::Exception("Expected a minimum of 3 vertices, got %d.", count);
|
||||
else if (count > b2_maxPolygonVertices)
|
||||
throw love::Exception("Expected a maximum of %d vertices, got %d.", b2_maxPolygonVertices, count);
|
||||
|
||||
b2Vec2 vecs[b2_maxPolygonVertices];
|
||||
|
||||
if (istable)
|
||||
{
|
||||
for (int i = 0; i < vcount; i++)
|
||||
{
|
||||
lua_rawgeti(L, 1, 1 + i * 2);
|
||||
lua_rawgeti(L, 1, 2 + i * 2);
|
||||
float x = (float)luaL_checknumber(L, -2);
|
||||
float y = (float)luaL_checknumber(L, -1);
|
||||
vecs[i] = Physics::scaleDown(b2Vec2(x, y));
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < vcount; i++)
|
||||
{
|
||||
float x = (float)luaL_checknumber(L, 1 + i * 2);
|
||||
float y = (float)luaL_checknumber(L, 2 + i * 2);
|
||||
vecs[i] = Physics::scaleDown(b2Vec2(x, y));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < count; i++)
|
||||
vecs[i] = Physics::scaleDown(b2Vec2(coords[i].x, coords[i].y));
|
||||
|
||||
b2PolygonShape *s = new b2PolygonShape();
|
||||
b2PolygonShape s;
|
||||
|
||||
try
|
||||
{
|
||||
s->Set(vecs, vcount);
|
||||
}
|
||||
catch (love::Exception &)
|
||||
{
|
||||
delete s;
|
||||
throw;
|
||||
}
|
||||
s.Set(vecs, count);
|
||||
|
||||
PolygonShape *p = new PolygonShape(s);
|
||||
luax_pushtype(L, p);
|
||||
p->release();
|
||||
return 1;
|
||||
return new PolygonShape(body, s);
|
||||
}
|
||||
|
||||
int Physics::newChainShape(lua_State *L)
|
||||
ChainShape *Physics::newChainShape(Body *body, bool loop, const Vector2 *coords, int count)
|
||||
{
|
||||
int argc = lua_gettop(L)-1; // first argument is looping
|
||||
std::vector<b2Vec2> vecs;
|
||||
|
||||
bool istable = lua_istable(L, 2);
|
||||
for (int i = 0; i < count; i++)
|
||||
vecs.push_back(Physics::scaleDown(b2Vec2(coords[i].x, coords[i].y)));
|
||||
|
||||
if (istable)
|
||||
argc = (int) luax_objlen(L, 2);
|
||||
b2ChainShape s;
|
||||
|
||||
if (argc == 0 || argc % 2 != 0)
|
||||
return luaL_error(L, "Number of vertex components must be a multiple of two.");
|
||||
|
||||
int vcount = argc/2;
|
||||
bool loop = luax_checkboolean(L, 1);
|
||||
b2Vec2 *vecs = new b2Vec2[vcount];
|
||||
|
||||
if (istable)
|
||||
{
|
||||
for (int i = 0; i < vcount; i++)
|
||||
{
|
||||
lua_rawgeti(L, 2, 1 + i * 2);
|
||||
lua_rawgeti(L, 2, 2 + i * 2);
|
||||
float x = (float)lua_tonumber(L, -2);
|
||||
float y = (float)lua_tonumber(L, -1);
|
||||
vecs[i] = Physics::scaleDown(b2Vec2(x, y));
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
}
|
||||
if (loop)
|
||||
s.CreateLoop(vecs.data(), count);
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < vcount; i++)
|
||||
{
|
||||
float x = (float)luaL_checknumber(L, 2 + i * 2);
|
||||
float y = (float)luaL_checknumber(L, 3 + i * 2);
|
||||
vecs[i] = Physics::scaleDown(b2Vec2(x, y));
|
||||
}
|
||||
}
|
||||
s.CreateChain(vecs.data(), count, vecs[0], vecs[count - 1]);
|
||||
|
||||
b2ChainShape *s = new b2ChainShape();
|
||||
|
||||
try
|
||||
{
|
||||
if (loop)
|
||||
s->CreateLoop(vecs, vcount);
|
||||
else
|
||||
s->CreateChain(vecs, vcount, vecs[0], vecs[vcount-1]);
|
||||
}
|
||||
catch (love::Exception &)
|
||||
{
|
||||
delete[] vecs;
|
||||
delete s;
|
||||
throw;
|
||||
}
|
||||
|
||||
delete[] vecs;
|
||||
|
||||
ChainShape *c = new ChainShape(s);
|
||||
luax_pushtype(L, c);
|
||||
c->release();
|
||||
return 1;
|
||||
return new ChainShape(body, s);
|
||||
}
|
||||
|
||||
DistanceJoint *Physics::newDistanceJoint(Body *body1, Body *body2, float x1, float y1, float x2, float y2, bool collideConnected)
|
||||
@@ -307,16 +299,10 @@ MotorJoint *Physics::newMotorJoint(Body *body1, Body *body2, float correctionFac
|
||||
return new MotorJoint(body1, body2, correctionFactor, collideConnected);
|
||||
}
|
||||
|
||||
|
||||
Fixture *Physics::newFixture(Body *body, Shape *shape, float density)
|
||||
{
|
||||
return new Fixture(body, shape, density);
|
||||
}
|
||||
|
||||
int Physics::getDistance(lua_State *L)
|
||||
{
|
||||
Fixture *fixtureA = luax_checktype<Fixture>(L, 1);
|
||||
Fixture *fixtureB = luax_checktype<Fixture>(L, 2);
|
||||
Shape *shapeA = luax_checktype<Shape>(L, 1);
|
||||
Shape *shapeB = luax_checktype<Shape>(L, 2);
|
||||
b2DistanceProxy pA, pB;
|
||||
b2DistanceInput i;
|
||||
b2DistanceOutput o;
|
||||
@@ -324,12 +310,15 @@ int Physics::getDistance(lua_State *L)
|
||||
c.count = 0;
|
||||
|
||||
luax_catchexcept(L, [&]() {
|
||||
pA.Set(fixtureA->fixture->GetShape(), 0);
|
||||
pB.Set(fixtureB->fixture->GetShape(), 0);
|
||||
if (!shapeA->isValid() || !shapeB->isValid())
|
||||
throw love::Exception("The given Shape is not active in the physics World.");
|
||||
|
||||
pA.Set(shapeA->fixture->GetShape(), 0);
|
||||
pB.Set(shapeB->fixture->GetShape(), 0);
|
||||
i.proxyA = pA;
|
||||
i.proxyB = pB;
|
||||
i.transformA = fixtureA->fixture->GetBody()->GetTransform();
|
||||
i.transformB = fixtureB->fixture->GetBody()->GetTransform();
|
||||
i.transformA = shapeA->fixture->GetBody()->GetTransform();
|
||||
i.transformB = shapeB->fixture->GetBody()->GetTransform();
|
||||
i.useRadii = true;
|
||||
b2Distance(&o, &c, &i);
|
||||
});
|
||||
|
||||
@@ -23,10 +23,11 @@
|
||||
|
||||
// LOVE
|
||||
#include "common/Module.h"
|
||||
#include "common/Vector.h"
|
||||
|
||||
#include "World.h"
|
||||
#include "Contact.h"
|
||||
#include "Body.h"
|
||||
#include "Fixture.h"
|
||||
#include "Shape.h"
|
||||
#include "CircleShape.h"
|
||||
#include "PolygonShape.h"
|
||||
@@ -93,10 +94,18 @@ public:
|
||||
Body *newBody(World *world, Body::Type type);
|
||||
|
||||
/**
|
||||
* Creates a new CircleShape at (0, 0).
|
||||
* @param radius The radius of the circle.
|
||||
* Convenience functions for creating a Body and Shape all in one call. The
|
||||
* body's world position is the center/average of the given coordinates,
|
||||
* and the shape is centered at the local origin.
|
||||
**/
|
||||
CircleShape *newCircleShape(float radius);
|
||||
Body *newCircleBody(World *world, Body::Type type, float x, float y, float radius);
|
||||
Body *newRectangleBody(World *world, Body::Type type, float x, float y, float w, float h, float angle);
|
||||
Body *newPolygonBody(World *world, Body::Type type, const Vector2 *coords, int count);
|
||||
Body *newEdgeBody(World *world, Body::Type type, float x1, float y1, float x2, float y2, bool oneSided);
|
||||
Body *newChainBody(World *world, Body::Type type, bool loop, const Vector2 *coords, int count);
|
||||
|
||||
// Necessary to support the deprecated newFixture API.
|
||||
Shape *newAttachedShape(Body *body, Shape *prototype, float density);
|
||||
|
||||
/**
|
||||
* Creates a new CircleShape at (x,y) in local coordinates.
|
||||
@@ -104,25 +113,7 @@ public:
|
||||
* @param y The offset along the y-axis.
|
||||
* @param radius The radius of the circle.
|
||||
**/
|
||||
CircleShape *newCircleShape(float x, float y, float radius);
|
||||
|
||||
/**
|
||||
* Shorthand for creating rectangular PolygonShapes. The rectangle
|
||||
* will be created at the local origin.
|
||||
* @param w The width of the rectangle.
|
||||
* @param h The height of the rectangle.
|
||||
**/
|
||||
PolygonShape *newRectangleShape(float w, float h);
|
||||
|
||||
/**
|
||||
* Shorthand for creating rectangular PolygonShapes. The rectangle
|
||||
* will be created at (x,y) in local coordinates.
|
||||
* @param x The offset along the x-axis.
|
||||
* @param y The offset along the y-axis.
|
||||
* @param w The width of the rectangle.
|
||||
* @param h The height of the rectangle.
|
||||
**/
|
||||
PolygonShape *newRectangleShape(float x, float y, float w, float h);
|
||||
CircleShape *newCircleShape(Body *body, float x, float y, float radius);
|
||||
|
||||
/**
|
||||
* Shorthand for creating rectangular PolygonShapes. The rectangle
|
||||
@@ -133,7 +124,7 @@ public:
|
||||
* @param h The height of the rectangle.
|
||||
* @param angle The angle of the rectangle. (rad)
|
||||
**/
|
||||
PolygonShape *newRectangleShape(float x, float y, float w, float h, float angle);
|
||||
PolygonShape *newRectangleShape(Body *body, float x, float y, float w, float h, float angle);
|
||||
|
||||
/**
|
||||
* Creates a new EdgeShape. The edge will be created from
|
||||
@@ -143,17 +134,17 @@ public:
|
||||
* @param x2 The x coordinate of the second point.
|
||||
* @param y2 The y coordinate of the second point.
|
||||
**/
|
||||
EdgeShape *newEdgeShape(float x1, float y1, float x2, float y2, bool oneSided);
|
||||
EdgeShape *newEdgeShape(Body *body, float x1, float y1, float x2, float y2, bool oneSided);
|
||||
|
||||
/**
|
||||
* Creates a new PolygonShape from a variable number of vertices.
|
||||
**/
|
||||
int newPolygonShape(lua_State *L);
|
||||
PolygonShape *newPolygonShape(Body *body, const Vector2 *coords, int count);
|
||||
|
||||
/**
|
||||
* Creates a new ChainShape from a variable number of vertices.
|
||||
**/
|
||||
int newChainShape(lua_State *L);
|
||||
ChainShape *newChainShape(Body *body, bool loop, const Vector2 *coords, int count);
|
||||
|
||||
/**
|
||||
* Creates a new DistanceJoint connecting body1 with body2.
|
||||
@@ -273,15 +264,6 @@ public:
|
||||
MotorJoint *newMotorJoint(Body *body1, Body *body2);
|
||||
MotorJoint *newMotorJoint(Body *body1, Body *body2, float correctionFactor, bool collideConnected);
|
||||
|
||||
/**
|
||||
* Creates a new Fixture attaching shape to body.
|
||||
* @param body The body to attach the Fixture to.
|
||||
* @param shape The shape to attach to the Fixture,
|
||||
* @param density The density of the Fixture.
|
||||
**/
|
||||
|
||||
Fixture *newFixture(Body *body, Shape *shape, float density);
|
||||
|
||||
/**
|
||||
* Calculates the distance between two Fixtures.
|
||||
* @param fixtureA The first Fixture.
|
||||
@@ -403,10 +385,15 @@ public:
|
||||
**/
|
||||
static void computeAngularFrequency(float &frequency, float &ratio, float stiffness, float damping, b2Body *bodyA, b2Body *bodyB);
|
||||
|
||||
b2BlockAllocator *getBlockAllocator() { return &blockAllocator; }
|
||||
|
||||
private:
|
||||
|
||||
// The length of one meter in pixels.
|
||||
static float meter;
|
||||
|
||||
b2BlockAllocator blockAllocator;
|
||||
|
||||
}; // Physics
|
||||
|
||||
} // box2d
|
||||
|
||||
@@ -34,8 +34,8 @@ namespace box2d
|
||||
|
||||
love::Type PolygonShape::type("PolygonShape", &Shape::type);
|
||||
|
||||
PolygonShape::PolygonShape(b2PolygonShape *p, bool own)
|
||||
: Shape(p, own)
|
||||
PolygonShape::PolygonShape(Body *body, const b2PolygonShape &p)
|
||||
: Shape(body, p)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ PolygonShape::~PolygonShape()
|
||||
|
||||
int PolygonShape::getPoints(lua_State *L)
|
||||
{
|
||||
throwIfShapeNotValid();
|
||||
love::luax_assert_argc(L, 0);
|
||||
b2PolygonShape *p = (b2PolygonShape *)shape;
|
||||
int count = p->m_count;
|
||||
@@ -59,6 +60,7 @@ int PolygonShape::getPoints(lua_State *L)
|
||||
|
||||
bool PolygonShape::validate() const
|
||||
{
|
||||
throwIfShapeNotValid();
|
||||
b2PolygonShape *p = (b2PolygonShape *)shape;
|
||||
return p->Validate();
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
* Create a new PolygonShape from a Box2D polygon definition.
|
||||
* @param p The polygon definition.
|
||||
**/
|
||||
PolygonShape(b2PolygonShape *p, bool own = true);
|
||||
PolygonShape(Body *body, const b2PolygonShape &p);
|
||||
|
||||
virtual ~PolygonShape();
|
||||
|
||||
|
||||
@@ -35,54 +35,357 @@ namespace physics
|
||||
namespace box2d
|
||||
{
|
||||
|
||||
Shape::Shape()
|
||||
Shape::Shape(Body *body, const b2Shape &shape)
|
||||
: shape(nullptr)
|
||||
, own(false)
|
||||
, shapeType(SHAPE_INVALID)
|
||||
, body(body)
|
||||
, fixture(nullptr)
|
||||
{
|
||||
}
|
||||
if (body)
|
||||
{
|
||||
b2FixtureDef def;
|
||||
def.shape = &shape;
|
||||
def.userData.pointer = (uintptr_t)this;
|
||||
|
||||
Shape::Shape(b2Shape *shape, bool own)
|
||||
: shape(shape)
|
||||
, own(own)
|
||||
{
|
||||
// 0 density stops CreateFixture from calling b2Body::ResetMassData().
|
||||
def.density = body->hasCustomMassData() ? 0.0f : 1.0f;
|
||||
|
||||
fixture = body->body->CreateFixture(&def);
|
||||
this->shape = fixture->GetShape();
|
||||
|
||||
if (body->hasCustomMassData())
|
||||
setDensity(1.0f);
|
||||
|
||||
retain(); // Shape::destroy does the release().
|
||||
}
|
||||
else
|
||||
{
|
||||
// Path to support deprecated APIs.
|
||||
auto physics = Module::getInstance<Physics>(Module::M_PHYSICS);
|
||||
this->shape = shape.Clone(physics->getBlockAllocator());
|
||||
own = true;
|
||||
}
|
||||
|
||||
switch (this->shape->GetType())
|
||||
{
|
||||
case b2Shape::e_circle:
|
||||
shapeType = SHAPE_CIRCLE;
|
||||
break;
|
||||
case b2Shape::e_polygon:
|
||||
shapeType = SHAPE_POLYGON;
|
||||
break;
|
||||
case b2Shape::e_edge:
|
||||
shapeType = SHAPE_EDGE;
|
||||
break;
|
||||
case b2Shape::e_chain:
|
||||
shapeType = SHAPE_CHAIN;
|
||||
break;
|
||||
default:
|
||||
shapeType = SHAPE_INVALID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Shape::~Shape()
|
||||
{
|
||||
if (shape && own)
|
||||
delete shape;
|
||||
{
|
||||
auto physics = Module::getInstance<Physics>(Module::M_PHYSICS);
|
||||
auto allocator = physics->getBlockAllocator();
|
||||
|
||||
// Taken from b2Fixture::Destroy. Not very pretty...
|
||||
switch (shapeType)
|
||||
{
|
||||
case SHAPE_CIRCLE:
|
||||
{
|
||||
b2CircleShape *s = (b2CircleShape*)shape;
|
||||
s->~b2CircleShape();
|
||||
allocator->Free(s, sizeof(b2CircleShape));
|
||||
break;
|
||||
}
|
||||
case SHAPE_EDGE:
|
||||
{
|
||||
b2EdgeShape *s = (b2EdgeShape*)shape;
|
||||
s->~b2EdgeShape();
|
||||
allocator->Free(s, sizeof(b2EdgeShape));
|
||||
break;
|
||||
}
|
||||
case SHAPE_POLYGON:
|
||||
{
|
||||
b2PolygonShape *s = (b2PolygonShape*)shape;
|
||||
s->~b2PolygonShape();
|
||||
allocator->Free(s, sizeof(b2PolygonShape));
|
||||
break;
|
||||
}
|
||||
case SHAPE_CHAIN:
|
||||
{
|
||||
b2ChainShape *s = (b2ChainShape*)shape;
|
||||
s->~b2ChainShape();
|
||||
allocator->Free(s, sizeof(b2ChainShape));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ref)
|
||||
delete ref;
|
||||
}
|
||||
|
||||
void Shape::destroy(bool implicit)
|
||||
{
|
||||
if (fixture == nullptr)
|
||||
return;
|
||||
|
||||
if (body->world->world->IsLocked())
|
||||
{
|
||||
// Called during time step. Save reference for destruction afterwards.
|
||||
this->retain();
|
||||
body->world->destructShapes.push_back(this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!implicit && fixture != nullptr)
|
||||
body->body->DestroyFixture(fixture);
|
||||
|
||||
fixture = nullptr;
|
||||
shape = nullptr;
|
||||
body = nullptr;
|
||||
|
||||
// Remove userdata reference to avoid it sticking around after GC
|
||||
if (ref)
|
||||
ref->unref();
|
||||
|
||||
// Box2D fixture destroyed. Release its reference to the love Shape.
|
||||
release();
|
||||
}
|
||||
|
||||
void Shape::throwIfFixtureNotValid() const
|
||||
{
|
||||
if (fixture == nullptr)
|
||||
throw love::Exception("Shape must be active in the physics World to use this method.");
|
||||
}
|
||||
|
||||
void Shape::throwIfShapeNotValid() const
|
||||
{
|
||||
if (shape == nullptr)
|
||||
throw love::Exception("Cannot call this method on a destroyed Shape.");
|
||||
}
|
||||
|
||||
Shape::Type Shape::getType() const
|
||||
{
|
||||
switch (shape->GetType())
|
||||
{
|
||||
case b2Shape::e_circle:
|
||||
return SHAPE_CIRCLE;
|
||||
case b2Shape::e_polygon:
|
||||
return SHAPE_POLYGON;
|
||||
case b2Shape::e_edge:
|
||||
return SHAPE_EDGE;
|
||||
case b2Shape::e_chain:
|
||||
return SHAPE_CHAIN;
|
||||
default:
|
||||
return SHAPE_INVALID;
|
||||
}
|
||||
return shapeType;
|
||||
}
|
||||
|
||||
void Shape::setFriction(float friction)
|
||||
{
|
||||
throwIfFixtureNotValid();
|
||||
fixture->SetFriction(friction);
|
||||
}
|
||||
|
||||
void Shape::setRestitution(float restitution)
|
||||
{
|
||||
throwIfFixtureNotValid();
|
||||
fixture->SetRestitution(restitution);
|
||||
}
|
||||
|
||||
void Shape::setDensity(float density)
|
||||
{
|
||||
throwIfFixtureNotValid();
|
||||
fixture->SetDensity(density);
|
||||
if (!body->hasCustomMassData())
|
||||
body->resetMassData();
|
||||
}
|
||||
|
||||
void Shape::setSensor(bool sensor)
|
||||
{
|
||||
throwIfFixtureNotValid();
|
||||
fixture->SetSensor(sensor);
|
||||
}
|
||||
|
||||
float Shape::getFriction() const
|
||||
{
|
||||
throwIfFixtureNotValid();
|
||||
return fixture->GetFriction();
|
||||
}
|
||||
|
||||
float Shape::getRestitution() const
|
||||
{
|
||||
throwIfFixtureNotValid();
|
||||
return fixture->GetRestitution();
|
||||
}
|
||||
|
||||
float Shape::getDensity() const
|
||||
{
|
||||
throwIfFixtureNotValid();
|
||||
return fixture->GetDensity();
|
||||
}
|
||||
|
||||
bool Shape::isSensor() const
|
||||
{
|
||||
throwIfFixtureNotValid();
|
||||
return fixture->IsSensor();
|
||||
}
|
||||
|
||||
Body *Shape::getBody() const
|
||||
{
|
||||
return body;
|
||||
}
|
||||
|
||||
float Shape::getRadius() const
|
||||
{
|
||||
throwIfShapeNotValid();
|
||||
return Physics::scaleUp(shape->m_radius);
|
||||
}
|
||||
|
||||
int Shape::getChildCount() const
|
||||
{
|
||||
throwIfShapeNotValid();
|
||||
return shape->GetChildCount();
|
||||
}
|
||||
|
||||
void Shape::setFilterData(int *v)
|
||||
{
|
||||
throwIfFixtureNotValid();
|
||||
b2Filter f;
|
||||
f.categoryBits = (uint16) v[0];
|
||||
f.maskBits = (uint16) v[1];
|
||||
f.groupIndex = (int16) v[2];
|
||||
fixture->SetFilterData(f);
|
||||
}
|
||||
|
||||
void Shape::getFilterData(int *v)
|
||||
{
|
||||
throwIfFixtureNotValid();
|
||||
b2Filter f = fixture->GetFilterData();
|
||||
v[0] = (int) f.categoryBits;
|
||||
v[1] = (int) f.maskBits;
|
||||
v[2] = (int) f.groupIndex;
|
||||
}
|
||||
|
||||
int Shape::setCategory(lua_State *L)
|
||||
{
|
||||
throwIfFixtureNotValid();
|
||||
b2Filter f = fixture->GetFilterData();
|
||||
f.categoryBits = (uint16)getBits(L);
|
||||
fixture->SetFilterData(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Shape::setMask(lua_State *L)
|
||||
{
|
||||
throwIfFixtureNotValid();
|
||||
b2Filter f = fixture->GetFilterData();
|
||||
f.maskBits = ~(uint16)getBits(L);
|
||||
fixture->SetFilterData(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Shape::setGroupIndex(int index)
|
||||
{
|
||||
throwIfFixtureNotValid();
|
||||
b2Filter f = fixture->GetFilterData();
|
||||
f.groupIndex = (uint16)index;
|
||||
fixture->SetFilterData(f);
|
||||
}
|
||||
|
||||
int Shape::getGroupIndex() const
|
||||
{
|
||||
throwIfFixtureNotValid();
|
||||
b2Filter f = fixture->GetFilterData();
|
||||
return f.groupIndex;
|
||||
}
|
||||
|
||||
int Shape::getCategory(lua_State *L)
|
||||
{
|
||||
throwIfFixtureNotValid();
|
||||
return pushBits(L, fixture->GetFilterData().categoryBits);
|
||||
}
|
||||
|
||||
int Shape::getMask(lua_State *L)
|
||||
{
|
||||
throwIfFixtureNotValid();
|
||||
return pushBits(L, ~(fixture->GetFilterData().maskBits));
|
||||
}
|
||||
|
||||
uint16 Shape::getBits(lua_State *L)
|
||||
{
|
||||
// Get number of args.
|
||||
bool istable = lua_istable(L, 1);
|
||||
int argc = istable ? (int) luax_objlen(L, 1) : lua_gettop(L);
|
||||
|
||||
// The new bitset.
|
||||
std::bitset<16> b;
|
||||
|
||||
for (int i = 1; i <= argc; i++)
|
||||
{
|
||||
size_t bpos = 0;
|
||||
|
||||
if (istable)
|
||||
{
|
||||
lua_rawgeti(L, 1, i);
|
||||
bpos = (size_t) (lua_tointeger(L, -1) - 1);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
else
|
||||
bpos = (size_t) (lua_tointeger(L, i) - 1);
|
||||
|
||||
if (bpos >= 16)
|
||||
luaL_error(L, "Values must be in range 1-16.");
|
||||
|
||||
b.set(bpos, true);
|
||||
}
|
||||
|
||||
return (uint16)b.to_ulong();
|
||||
}
|
||||
|
||||
int Shape::pushBits(lua_State *L, uint16 bits)
|
||||
{
|
||||
// Create a bitset.
|
||||
std::bitset<16> b((int)bits);
|
||||
|
||||
// Push all set bits.
|
||||
for (int i = 0; i<16; i++)
|
||||
if (b.test(i))
|
||||
lua_pushinteger(L, i+1);
|
||||
|
||||
// Count number of set bits.
|
||||
return (int)b.count();
|
||||
}
|
||||
|
||||
int Shape::setUserData(lua_State *L)
|
||||
{
|
||||
love::luax_assert_argc(L, 1, 1);
|
||||
|
||||
if(!ref)
|
||||
ref = new Reference();
|
||||
|
||||
ref->ref(L);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Shape::getUserData(lua_State *L)
|
||||
{
|
||||
if (ref != nullptr)
|
||||
ref->push(L);
|
||||
else
|
||||
lua_pushnil(L);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool Shape::testPoint(float x, float y) const
|
||||
{
|
||||
throwIfFixtureNotValid();
|
||||
return fixture->TestPoint(Physics::scaleDown(b2Vec2(x, y)));
|
||||
}
|
||||
|
||||
bool Shape::testPoint(float x, float y, float r, float px, float py) const
|
||||
{
|
||||
throwIfShapeNotValid();
|
||||
b2Vec2 point(px, py);
|
||||
b2Transform transform(Physics::scaleDown(b2Vec2(x, y)), b2Rot(r));
|
||||
return shape->TestPoint(transform, Physics::scaleDown(point));
|
||||
@@ -95,18 +398,34 @@ int Shape::rayCast(lua_State *L) const
|
||||
float p2x = Physics::scaleDown((float)luaL_checknumber(L, 3));
|
||||
float p2y = Physics::scaleDown((float)luaL_checknumber(L, 4));
|
||||
float maxFraction = (float)luaL_checknumber(L, 5);
|
||||
float x = Physics::scaleDown((float)luaL_checknumber(L, 6));
|
||||
float y = Physics::scaleDown((float)luaL_checknumber(L, 7));
|
||||
float r = (float)luaL_checknumber(L, 8);
|
||||
int childIndex = (int) luaL_optinteger(L, 9, 1) - 1; // Convert from 1-based index
|
||||
|
||||
b2RayCastInput input;
|
||||
b2RayCastOutput output;
|
||||
input.p1.Set(p1x, p1y);
|
||||
input.p2.Set(p2x, p2y);
|
||||
input.maxFraction = maxFraction;
|
||||
b2Transform transform(b2Vec2(x, y), b2Rot(r));
|
||||
b2RayCastOutput output;
|
||||
if (!shape->RayCast(&output, input, transform, childIndex))
|
||||
return 0; // No hit.
|
||||
|
||||
if (lua_isnoneornil(L, 7))
|
||||
{
|
||||
throwIfFixtureNotValid();
|
||||
int childIndex = (int) luaL_optinteger(L, 6, 1) - 1; // Convert from 1-based index
|
||||
if (!fixture->RayCast(&output, input, childIndex))
|
||||
return 0; // Nothing hit.
|
||||
}
|
||||
else
|
||||
{
|
||||
throwIfShapeNotValid();
|
||||
float x = Physics::scaleDown((float)luaL_checknumber(L, 6));
|
||||
float y = Physics::scaleDown((float)luaL_checknumber(L, 7));
|
||||
float r = (float)luaL_checknumber(L, 8);
|
||||
int childIndex = (int) luaL_optinteger(L, 9, 1) - 1; // Convert from 1-based index
|
||||
|
||||
b2Transform transform(b2Vec2(x, y), b2Rot(r));
|
||||
|
||||
if (!shape->RayCast(&output, input, transform, childIndex))
|
||||
return 0; // No hit.
|
||||
}
|
||||
|
||||
lua_pushnumber(L, output.normal.x);
|
||||
lua_pushnumber(L, output.normal.y);
|
||||
lua_pushnumber(L, output.fraction);
|
||||
@@ -115,6 +434,7 @@ int Shape::rayCast(lua_State *L) const
|
||||
|
||||
int Shape::computeAABB(lua_State *L) const
|
||||
{
|
||||
throwIfShapeNotValid();
|
||||
float x = Physics::scaleDown((float)luaL_checknumber(L, 1));
|
||||
float y = Physics::scaleDown((float)luaL_checknumber(L, 2));
|
||||
float r = (float)luaL_checknumber(L, 3);
|
||||
@@ -132,6 +452,7 @@ int Shape::computeAABB(lua_State *L) const
|
||||
|
||||
int Shape::computeMass(lua_State *L) const
|
||||
{
|
||||
throwIfShapeNotValid();
|
||||
float density = (float)luaL_checknumber(L, 1);
|
||||
b2MassData data;
|
||||
shape->ComputeMass(&data, density);
|
||||
@@ -143,6 +464,33 @@ int Shape::computeMass(lua_State *L) const
|
||||
return 4;
|
||||
}
|
||||
|
||||
int Shape::getBoundingBox(lua_State *L) const
|
||||
{
|
||||
throwIfFixtureNotValid();
|
||||
int childIndex = (int) luaL_optinteger(L, 1, 1) - 1; // Convert from 1-based index
|
||||
b2AABB box;
|
||||
luax_catchexcept(L, [&]() { box = fixture->GetAABB(childIndex); });
|
||||
box = Physics::scaleUp(box);
|
||||
lua_pushnumber(L, box.lowerBound.x);
|
||||
lua_pushnumber(L, box.lowerBound.y);
|
||||
lua_pushnumber(L, box.upperBound.x);
|
||||
lua_pushnumber(L, box.upperBound.y);
|
||||
return 4;
|
||||
}
|
||||
|
||||
int Shape::getMassData(lua_State *L) const
|
||||
{
|
||||
throwIfFixtureNotValid();
|
||||
b2MassData data;
|
||||
fixture->GetMassData(&data);
|
||||
b2Vec2 center = Physics::scaleUp(data.center);
|
||||
lua_pushnumber(L, center.x);
|
||||
lua_pushnumber(L, center.y);
|
||||
lua_pushnumber(L, data.mass);
|
||||
lua_pushnumber(L, data.I);
|
||||
return 4;
|
||||
}
|
||||
|
||||
} // box2d
|
||||
} // physics
|
||||
} // love
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
// LOVE
|
||||
#include "physics/Shape.h"
|
||||
#include "physics/box2d/Body.h"
|
||||
#include "common/Reference.h"
|
||||
|
||||
// Box2D
|
||||
#include <box2d/Box2D.h>
|
||||
@@ -45,34 +46,155 @@ class Shape : public love::physics::Shape
|
||||
{
|
||||
public:
|
||||
|
||||
friend class Fixture;
|
||||
friend class Physics;
|
||||
|
||||
/**
|
||||
* Creates a Shape.
|
||||
**/
|
||||
Shape();
|
||||
Shape(b2Shape *shape, bool own = true);
|
||||
Shape(Body *body, const b2Shape &shape);
|
||||
|
||||
virtual ~Shape();
|
||||
|
||||
void destroy(bool implicit = false);
|
||||
|
||||
/**
|
||||
* Returns true if the shape is active in a Box2D world.
|
||||
**/
|
||||
bool isValid() const { return fixture != nullptr; }
|
||||
|
||||
/**
|
||||
* Returns true if the shape has not been destroyed.
|
||||
**/
|
||||
bool isShapeValid() const { return shape != nullptr; }
|
||||
|
||||
/**
|
||||
* Checks whether this Shape acts as a sensor.
|
||||
**/
|
||||
bool isSensor() const;
|
||||
|
||||
/**
|
||||
* Set whether this Shape should be a sensor or not.
|
||||
**/
|
||||
void setSensor(bool sensor);
|
||||
|
||||
/**
|
||||
* Gets the Body this Shape is attached to.
|
||||
**/
|
||||
Body *getBody() const;
|
||||
|
||||
/**
|
||||
* Sets the filter data. An integer array is used even though the
|
||||
* first two elements are unsigned shorts. The elements are:
|
||||
* category (16-bits), mask (16-bits) and group (32-bits/int).
|
||||
**/
|
||||
void setFilterData(int *v);
|
||||
|
||||
/**
|
||||
* Gets the filter data. An integer array is used even though the
|
||||
* first two elements are unsigned shorts. The elements are:
|
||||
* category (16-bits), mask (16-bits) and group (32-bits/int).
|
||||
**/
|
||||
void getFilterData(int *v);
|
||||
|
||||
/**
|
||||
* This function stores an in-C reference to
|
||||
* arbitrary Lua data in the Shape object.
|
||||
**/
|
||||
int setUserData(lua_State *L);
|
||||
|
||||
/**
|
||||
* Gets the data set with setUserData. If no
|
||||
* data is set, nil is returned.
|
||||
**/
|
||||
int getUserData(lua_State *L);
|
||||
|
||||
/**
|
||||
* Sets the friction of the Shape.
|
||||
**/
|
||||
void setFriction(float friction);
|
||||
|
||||
/**
|
||||
* Sets the restitution for the Shape.
|
||||
**/
|
||||
void setRestitution(float restitution);
|
||||
|
||||
/**
|
||||
* Sets the density of the Shape.
|
||||
**/
|
||||
void setDensity(float density);
|
||||
|
||||
/**
|
||||
* Gets the friction of the Shape.
|
||||
**/
|
||||
float getFriction() const;
|
||||
|
||||
/**
|
||||
* Gets the restitution of the Shape.
|
||||
**/
|
||||
float getRestitution() const;
|
||||
|
||||
/**
|
||||
* Gets the density of the Shape.
|
||||
**/
|
||||
float getDensity() const;
|
||||
|
||||
/**
|
||||
* Checks if a point is inside the Shape.
|
||||
**/
|
||||
bool testPoint(float x, float y) const;
|
||||
bool testPoint(float x, float y, float r, float px, float py) const;
|
||||
|
||||
/**
|
||||
* Gets the type of Shape. Useful for
|
||||
* debug drawing.
|
||||
**/
|
||||
Type getType() const;
|
||||
|
||||
float getRadius() const;
|
||||
int getChildCount() const;
|
||||
bool testPoint(float x, float y, float r, float px, float py) const;
|
||||
int rayCast(lua_State *L) const;
|
||||
int computeAABB(lua_State *L) const;
|
||||
int computeMass(lua_State *L) const;
|
||||
|
||||
void setGroupIndex(int index);
|
||||
int getGroupIndex() const;
|
||||
|
||||
int setCategory(lua_State *L);
|
||||
int setMask(lua_State *L);
|
||||
int getCategory(lua_State *L);
|
||||
int getMask(lua_State *L);
|
||||
uint16 getBits(lua_State *L);
|
||||
int pushBits(lua_State *L, uint16 bits);
|
||||
|
||||
/**
|
||||
* Gets the bounding box for this Shape.
|
||||
**/
|
||||
int getBoundingBox(lua_State *L) const;
|
||||
|
||||
/**
|
||||
* Gets the mass data for this Shape.
|
||||
* This operation may be expensive.
|
||||
**/
|
||||
int getMassData(lua_State *L) const;
|
||||
|
||||
void throwIfFixtureNotValid() const;
|
||||
void throwIfShapeNotValid() const;
|
||||
|
||||
protected:
|
||||
|
||||
// The Box2D shape.
|
||||
b2Shape *shape;
|
||||
bool own;
|
||||
};
|
||||
|
||||
Shape::Type shapeType;
|
||||
|
||||
Body *body;
|
||||
b2Fixture *fixture;
|
||||
|
||||
// Reference to arbitrary data.
|
||||
Reference* ref = nullptr;
|
||||
|
||||
}; // Shape
|
||||
|
||||
} // box2d
|
||||
} // physics
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
#include "World.h"
|
||||
|
||||
#include "Fixture.h"
|
||||
#include "Shape.h"
|
||||
#include "Contact.h"
|
||||
#include "Physics.h"
|
||||
@@ -28,6 +27,7 @@
|
||||
|
||||
// Needed for World::getJoints. It should be moved to wrapper code...
|
||||
#include "wrap_Joint.h"
|
||||
#include "wrap_Shape.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
@@ -58,22 +58,22 @@ void World::ContactCallback::process(b2Contact *contact, const b2ContactImpulse
|
||||
{
|
||||
ref->push(L);
|
||||
|
||||
// Push first fixture.
|
||||
// Push first shape.
|
||||
{
|
||||
Fixture *a = (Fixture *)(contact->GetFixtureA()->GetUserData().pointer);
|
||||
Shape *a = (Shape *)(contact->GetFixtureA()->GetUserData().pointer);
|
||||
if (a != nullptr)
|
||||
luax_pushtype(L, a);
|
||||
luax_pushshape(L, a);
|
||||
else
|
||||
throw love::Exception("A fixture has escaped Memoizer!");
|
||||
throw love::Exception("A Shape has escaped Memoizer!");
|
||||
}
|
||||
|
||||
// Push second fixture.
|
||||
// Push second shape.
|
||||
{
|
||||
Fixture *b = (Fixture *)(contact->GetFixtureB()->GetUserData().pointer);
|
||||
Shape *b = (Shape *)(contact->GetFixtureB()->GetUserData().pointer);
|
||||
if (b != nullptr)
|
||||
luax_pushtype(L, b);
|
||||
luax_pushshape(L, b);
|
||||
else
|
||||
throw love::Exception("A fixture has escaped Memoizer!");
|
||||
throw love::Exception("A Shape has escaped Memoizer!");
|
||||
}
|
||||
|
||||
Contact *cobj = (Contact *)world->findObject(contact);
|
||||
@@ -112,32 +112,17 @@ World::ContactFilter::~ContactFilter()
|
||||
delete ref;
|
||||
}
|
||||
|
||||
bool World::ContactFilter::process(Fixture *a, Fixture *b)
|
||||
bool World::ContactFilter::process(Shape *a, Shape *b)
|
||||
{
|
||||
// Handle masks, reimplemented from the manual
|
||||
int filterA[3], filterB[3];
|
||||
// [0] categoryBits
|
||||
// [1] maskBits
|
||||
// [2] groupIndex
|
||||
a->getFilterData(filterA);
|
||||
b->getFilterData(filterB);
|
||||
|
||||
if (filterA[2] != 0 && // 0 is the default group, so this does not count
|
||||
filterA[2] == filterB[2]) // if they are in the same group
|
||||
return filterA[2] > 0; // Negative indexes mean you don't collide
|
||||
|
||||
if ((filterA[1] & filterB[0]) == 0 ||
|
||||
(filterB[1] & filterA[0]) == 0)
|
||||
return false; // A and B aren't set to collide
|
||||
|
||||
if (ref != nullptr && L != nullptr)
|
||||
{
|
||||
ref->push(L);
|
||||
luax_pushtype(L, a);
|
||||
luax_pushtype(L, b);
|
||||
luax_pushshape(L, a);
|
||||
luax_pushshape(L, b);
|
||||
lua_call(L, 2, 1);
|
||||
return luax_toboolean(L, -1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -159,10 +144,10 @@ bool World::QueryCallback::ReportFixture(b2Fixture *fixture)
|
||||
if (L != nullptr)
|
||||
{
|
||||
lua_pushvalue(L, funcidx);
|
||||
Fixture *f = (Fixture *)(fixture->GetUserData().pointer);
|
||||
Shape *f = (Shape *)(fixture->GetUserData().pointer);
|
||||
if (!f)
|
||||
throw love::Exception("A fixture has escaped Memoizer!");
|
||||
luax_pushtype(L, f);
|
||||
throw love::Exception("A Shape has escaped Memoizer!");
|
||||
luax_pushshape(L, f);
|
||||
for (int i = 1; i <= userargs; i++)
|
||||
lua_pushvalue(L, funcidx + i);
|
||||
lua_call(L, 1 + userargs, 1);
|
||||
@@ -191,10 +176,10 @@ bool World::CollectCallback::ReportFixture(b2Fixture *f)
|
||||
if (categoryMask != 0xFFFF && (categoryMask & f->GetFilterData().categoryBits) == 0)
|
||||
return true;
|
||||
|
||||
Fixture *fixture = (Fixture *)(f->GetUserData().pointer);
|
||||
if (!fixture)
|
||||
throw love::Exception("A fixture has escaped Memoizer!");
|
||||
luax_pushtype(L, fixture);
|
||||
Shape *shape = (Shape *)(f->GetUserData().pointer);
|
||||
if (!shape)
|
||||
throw love::Exception("A Shape has escaped Memoizer!");
|
||||
luax_pushshape(L, shape);
|
||||
lua_rawseti(L, -2, i);
|
||||
i++;
|
||||
return true;
|
||||
@@ -218,10 +203,10 @@ float World::RayCastCallback::ReportFixture(b2Fixture *fixture, const b2Vec2 &po
|
||||
if (L != nullptr)
|
||||
{
|
||||
lua_pushvalue(L, funcidx);
|
||||
Fixture *f = (Fixture *)(fixture->GetUserData().pointer);
|
||||
Shape *f = (Shape *)(fixture->GetUserData().pointer);
|
||||
if (!f)
|
||||
throw love::Exception("A fixture has escaped Memoizer!");
|
||||
luax_pushtype(L, f);
|
||||
throw love::Exception("A Shape has escaped Memoizer!");
|
||||
luax_pushshape(L, f);
|
||||
b2Vec2 scaledPoint = Physics::scaleUp(point);
|
||||
lua_pushnumber(L, scaledPoint.x);
|
||||
lua_pushnumber(L, scaledPoint.y);
|
||||
@@ -267,9 +252,9 @@ float World::RayCastOneCallback::ReportFixture(b2Fixture *fixture, const b2Vec2
|
||||
|
||||
void World::SayGoodbye(b2Fixture *fixture)
|
||||
{
|
||||
Fixture *f = (Fixture *)(fixture->GetUserData().pointer);
|
||||
Shape *s = (Shape *)(fixture->GetUserData().pointer);
|
||||
// Hint implicit destruction with true.
|
||||
if (f) f->destroy(true);
|
||||
if (s) s->destroy(true);
|
||||
}
|
||||
|
||||
void World::SayGoodbye(b2Joint *joint)
|
||||
@@ -336,11 +321,11 @@ void World::update(float dt, int velocityIterations, int positionIterations)
|
||||
// Release for reference in vector.
|
||||
b->release();
|
||||
}
|
||||
for (Fixture *f : destructFixtures)
|
||||
for (Shape *s : destructShapes)
|
||||
{
|
||||
if (f->isValid()) f->destroy();
|
||||
if (s->isValid()) s->destroy();
|
||||
// Release for reference in vector.
|
||||
f->release();
|
||||
s->release();
|
||||
}
|
||||
for (Joint *j : destructJoints)
|
||||
{
|
||||
@@ -349,7 +334,7 @@ void World::update(float dt, int velocityIterations, int positionIterations)
|
||||
j->release();
|
||||
}
|
||||
destructBodies.clear();
|
||||
destructFixtures.clear();
|
||||
destructShapes.clear();
|
||||
destructJoints.clear();
|
||||
|
||||
if (destructWorld)
|
||||
@@ -384,11 +369,24 @@ void World::PostSolve(b2Contact *contact, const b2ContactImpulse *impulse)
|
||||
|
||||
bool World::ShouldCollide(b2Fixture *fixtureA, b2Fixture *fixtureB)
|
||||
{
|
||||
// Fixtures should be memoized, if we created them
|
||||
Fixture *a = (Fixture *)(fixtureA->GetUserData().pointer);
|
||||
Fixture *b = (Fixture *)(fixtureB->GetUserData().pointer);
|
||||
const b2Filter &filterA = fixtureA->GetFilterData();
|
||||
const b2Filter &filterB = fixtureB->GetFilterData();
|
||||
|
||||
// From b2_world_callbacks.cpp
|
||||
// 0 is the default group index. If they're customized to be the same group,
|
||||
// allow collisions if it's positive and disallow if it's negative.
|
||||
if (filterA.groupIndex != 0 && filterA.groupIndex == filterB.groupIndex)
|
||||
return filterA.groupIndex > 0;
|
||||
|
||||
if ((filterA.maskBits & filterB.categoryBits) == 0 || (filterA.categoryBits & filterB.maskBits) == 0)
|
||||
return false;
|
||||
|
||||
// Shapes should be memoized, if we created them
|
||||
Shape *a = (Shape *)(fixtureA->GetUserData().pointer);
|
||||
Shape *b = (Shape *)(fixtureB->GetUserData().pointer);
|
||||
if (!a || !b)
|
||||
throw love::Exception("A fixture has escaped Memoizer!");
|
||||
throw love::Exception("A Shape has escaped Memoizer!");
|
||||
|
||||
return filter.process(a, b);
|
||||
}
|
||||
|
||||
@@ -597,7 +595,7 @@ b2Body *World::getGroundBody() const
|
||||
return groundBody;
|
||||
}
|
||||
|
||||
int World::queryFixturesInArea(lua_State *L)
|
||||
int World::queryShapesInArea(lua_State *L)
|
||||
{
|
||||
b2AABB box;
|
||||
float lx = (float)luaL_checknumber(L, 1);
|
||||
@@ -612,7 +610,7 @@ int World::queryFixturesInArea(lua_State *L)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int World::getFixturesInArea(lua_State *L)
|
||||
int World::getShapesInArea(lua_State *L)
|
||||
{
|
||||
float lx = (float)luaL_checknumber(L, 1);
|
||||
float ly = (float)luaL_checknumber(L, 2);
|
||||
@@ -654,10 +652,10 @@ int World::rayCastAny(lua_State *L)
|
||||
world->RayCast(&raycast, v1, v2);
|
||||
if (raycast.hitFixture)
|
||||
{
|
||||
Fixture *f = (Fixture *)(raycast.hitFixture->GetUserData().pointer);
|
||||
Shape *f = (Shape *)(raycast.hitFixture->GetUserData().pointer);
|
||||
if (f == nullptr)
|
||||
return luaL_error(L, "A fixture has escaped Memoizer!");
|
||||
luax_pushtype(L, f);
|
||||
return luaL_error(L, "A Shape has escaped Memoizer!");
|
||||
luax_pushshape(L, f);
|
||||
|
||||
b2Vec2 hitPoint = Physics::scaleUp(raycast.hitPoint);
|
||||
lua_pushnumber(L, hitPoint.x);
|
||||
@@ -683,10 +681,10 @@ int World::rayCastClosest(lua_State *L)
|
||||
world->RayCast(&raycast, v1, v2);
|
||||
if (raycast.hitFixture)
|
||||
{
|
||||
Fixture *f = (Fixture *)(raycast.hitFixture->GetUserData().pointer);
|
||||
Shape *f = (Shape *)(raycast.hitFixture->GetUserData().pointer);
|
||||
if (f == nullptr)
|
||||
return luaL_error(L, "A fixture has escaped Memoizer!");
|
||||
luax_pushtype(L, f);
|
||||
return luaL_error(L, "A Shape has escaped Memoizer!");
|
||||
luax_pushshape(L, f);
|
||||
|
||||
b2Vec2 hitPoint = Physics::scaleUp(raycast.hitPoint);
|
||||
lua_pushnumber(L, hitPoint.x);
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace box2d
|
||||
|
||||
class Contact;
|
||||
class Body;
|
||||
class Fixture;
|
||||
class Shape;
|
||||
class Joint;
|
||||
|
||||
/**
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
friend class DistanceJoint;
|
||||
friend class MouseJoint;
|
||||
friend class Body;
|
||||
friend class Fixture;
|
||||
friend class Shape;
|
||||
|
||||
static love::Type type;
|
||||
|
||||
@@ -87,7 +87,7 @@ public:
|
||||
lua_State *L;
|
||||
ContactFilter();
|
||||
~ContactFilter();
|
||||
bool process(Fixture *a, Fixture *b);
|
||||
bool process(Shape *a, Shape *b);
|
||||
};
|
||||
|
||||
class QueryCallback : public b2QueryCallback
|
||||
@@ -302,14 +302,14 @@ public:
|
||||
b2Body *getGroundBody() const;
|
||||
|
||||
/**
|
||||
* Calls a callback on all fixtures that overlap a given bounding box.
|
||||
* Calls a callback on all Shapes that overlap a given bounding box.
|
||||
**/
|
||||
int queryFixturesInArea(lua_State *L);
|
||||
int queryShapesInArea(lua_State *L);
|
||||
|
||||
/**
|
||||
* Gets all fixtures that overlap a given bounding box.
|
||||
* Gets all Shapes that overlap a given bounding box.
|
||||
**/
|
||||
int getFixturesInArea(lua_State *L);
|
||||
int getShapesInArea(lua_State *L);
|
||||
|
||||
/**
|
||||
* Raycasts the World for all Fixtures in the path of the ray.
|
||||
@@ -338,7 +338,7 @@ private:
|
||||
|
||||
// The list of to be destructed bodies.
|
||||
std::vector<Body *> destructBodies;
|
||||
std::vector<Fixture *> destructFixtures;
|
||||
std::vector<Shape *> destructShapes;
|
||||
std::vector<Joint *> destructJoints;
|
||||
bool destructWorld;
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "wrap_Body.h"
|
||||
#include "wrap_Physics.h"
|
||||
#include "wrap_Shape.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
@@ -161,6 +162,13 @@ int w_Body_getMassData(lua_State *L)
|
||||
return t->getMassData(L);
|
||||
}
|
||||
|
||||
int w_Body_hasCustomMassData(lua_State *L)
|
||||
{
|
||||
Body *t = luax_checkbody(L, 1);
|
||||
luax_pushboolean(L, t->hasCustomMassData());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Body_getAngularDamping(lua_State *L)
|
||||
{
|
||||
Body *t = luax_checkbody(L, 1);
|
||||
@@ -599,15 +607,32 @@ int w_Body_getWorld(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Body_getFixtures(lua_State *L)
|
||||
int w_Body_getShape(lua_State *L)
|
||||
{
|
||||
Body *t = luax_checkbody(L, 1);
|
||||
Shape *s = t->getShape();
|
||||
if (s)
|
||||
luax_pushshape(L, s);
|
||||
else
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Body_getShapes(lua_State *L)
|
||||
{
|
||||
Body *t = luax_checkbody(L, 1);
|
||||
lua_remove(L, 1);
|
||||
int n = 0;
|
||||
luax_catchexcept(L, [&](){ n = t->getFixtures(L); });
|
||||
luax_catchexcept(L, [&](){ n = t->getShapes(L); });
|
||||
return n;
|
||||
}
|
||||
|
||||
int w_Body_getFixtures(lua_State *L)
|
||||
{
|
||||
luax_markdeprecated(L, 1, "Body:getFixtures", API_METHOD, DEPRECATED_REPLACED, "Body:getShapes");
|
||||
return w_Body_getShapes(L);
|
||||
}
|
||||
|
||||
int w_Body_getJoints(lua_State *L)
|
||||
{
|
||||
Body *t = luax_checkbody(L, 1);
|
||||
@@ -670,6 +695,7 @@ static const luaL_Reg w_Body_functions[] =
|
||||
{ "getMass", w_Body_getMass },
|
||||
{ "getInertia", w_Body_getInertia },
|
||||
{ "getMassData", w_Body_getMassData },
|
||||
{ "hasCustomMassData", w_Body_hasCustomMassData },
|
||||
{ "getAngularDamping", w_Body_getAngularDamping },
|
||||
{ "getLinearDamping", w_Body_getLinearDamping },
|
||||
{ "getGravityScale", w_Body_getGravityScale },
|
||||
@@ -713,7 +739,8 @@ static const luaL_Reg w_Body_functions[] =
|
||||
{ "isFixedRotation", w_Body_isFixedRotation },
|
||||
{ "isTouching", w_Body_isTouching },
|
||||
{ "getWorld", w_Body_getWorld },
|
||||
{ "getFixtures", w_Body_getFixtures },
|
||||
{ "getShape", w_Body_getShape },
|
||||
{ "getShapes", w_Body_getShapes },
|
||||
{ "getJoints", w_Body_getJoints },
|
||||
{ "getContacts", w_Body_getContacts },
|
||||
{ "destroy", w_Body_destroy },
|
||||
@@ -721,6 +748,9 @@ static const luaL_Reg w_Body_functions[] =
|
||||
{ "setUserData", w_Body_setUserData },
|
||||
{ "getUserData", w_Body_getUserData },
|
||||
|
||||
// Deprecated
|
||||
{ "getFixtures", w_Body_getFixtures },
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
@@ -54,9 +54,10 @@ int w_ChainShape_setPreviousVertex(lua_State *L)
|
||||
|
||||
int w_ChainShape_getChildEdge(lua_State *L)
|
||||
{
|
||||
luax_markdeprecated(L, 1, "ChainShape:getChildEdge", API_METHOD, DEPRECATED_NO_REPLACEMENT, nullptr);
|
||||
ChainShape *c = luax_checkchainshape(L, 1);
|
||||
int index = (int) luaL_checkinteger(L, 2) - 1; // Convert from 1-based index
|
||||
EdgeShape *e = 0;
|
||||
EdgeShape *e = nullptr;
|
||||
luax_catchexcept(L, [&](){ e = c->getChildEdge(index); });
|
||||
luax_pushtype(L, e);
|
||||
e->release();
|
||||
@@ -66,7 +67,8 @@ int w_ChainShape_getChildEdge(lua_State *L)
|
||||
int w_ChainShape_getVertexCount(lua_State *L)
|
||||
{
|
||||
ChainShape *c = luax_checkchainshape(L, 1);
|
||||
int count = c->getVertexCount();
|
||||
int count = 0;
|
||||
luax_catchexcept(L, [&]() { count = c->getVertexCount(); });
|
||||
lua_pushinteger(L, count);
|
||||
return 1;
|
||||
}
|
||||
@@ -85,7 +87,8 @@ int w_ChainShape_getPoint(lua_State *L)
|
||||
int w_ChainShape_getNextVertex(lua_State *L)
|
||||
{
|
||||
ChainShape *c = luax_checkchainshape(L, 1);
|
||||
b2Vec2 v = c->getNextVertex();
|
||||
b2Vec2 v;
|
||||
luax_catchexcept(L, [&]() { v = c->getNextVertex(); });
|
||||
lua_pushnumber(L, v.x);
|
||||
lua_pushnumber(L, v.y);
|
||||
return 2;
|
||||
@@ -94,7 +97,8 @@ int w_ChainShape_getNextVertex(lua_State *L)
|
||||
int w_ChainShape_getPreviousVertex(lua_State *L)
|
||||
{
|
||||
ChainShape *c = luax_checkchainshape(L, 1);
|
||||
b2Vec2 v = c->getPreviousVertex();
|
||||
b2Vec2 v;
|
||||
luax_catchexcept(L, [&]() { v = c->getPreviousVertex(); });
|
||||
lua_pushnumber(L, v.x);
|
||||
lua_pushnumber(L, v.y);
|
||||
return 2;
|
||||
@@ -103,7 +107,8 @@ int w_ChainShape_getPreviousVertex(lua_State *L)
|
||||
int w_ChainShape_getPoints(lua_State *L)
|
||||
{
|
||||
ChainShape *c = luax_checkchainshape(L, 1);
|
||||
const b2Vec2 *verts = c->getPoints();
|
||||
const b2Vec2 *verts;
|
||||
luax_catchexcept(L, [&]() { verts = c->getPoints(); });
|
||||
int count = c->getVertexCount();
|
||||
if (!lua_checkstack(L, count*2))
|
||||
return luaL_error(L, "Too many return values");
|
||||
|
||||
@@ -35,7 +35,9 @@ CircleShape *luax_checkcircleshape(lua_State *L, int idx)
|
||||
int w_CircleShape_getRadius(lua_State *L)
|
||||
{
|
||||
CircleShape *c = luax_checkcircleshape(L, 1);
|
||||
lua_pushnumber(L, c->getRadius());
|
||||
float r = 0;
|
||||
luax_catchexcept(L, [&]() { r = c->getRadius(); });
|
||||
lua_pushnumber(L, r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -43,7 +45,7 @@ int w_CircleShape_setRadius(lua_State *L)
|
||||
{
|
||||
CircleShape *c = luax_checkcircleshape(L, 1);
|
||||
float r = (float)luaL_checknumber(L, 2);
|
||||
c->setRadius(r);
|
||||
luax_catchexcept(L, [&]() { c->setRadius(r); });
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -51,7 +53,7 @@ int w_CircleShape_getPoint(lua_State *L)
|
||||
{
|
||||
CircleShape *c = luax_checkcircleshape(L, 1);
|
||||
float x, y;
|
||||
c->getPoint(x, y);
|
||||
luax_catchexcept(L, [&]() { c->getPoint(x, y); });
|
||||
lua_pushnumber(L, x);
|
||||
lua_pushnumber(L, y);
|
||||
return 2;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
**/
|
||||
|
||||
#include "wrap_Contact.h"
|
||||
#include "Fixture.h"
|
||||
#include "wrap_Shape.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
@@ -139,18 +139,24 @@ int w_Contact_getChildren(lua_State *L)
|
||||
return 2;
|
||||
}
|
||||
|
||||
int w_Contact_getFixtures(lua_State *L)
|
||||
int w_Contact_getShapes(lua_State *L)
|
||||
{
|
||||
Contact *t = luax_checkcontact(L, 1);
|
||||
Fixture *a = nullptr;
|
||||
Fixture *b = nullptr;
|
||||
luax_catchexcept(L, [&](){ t->getFixtures(a, b); });
|
||||
Shape *a = nullptr;
|
||||
Shape *b = nullptr;
|
||||
luax_catchexcept(L, [&](){ t->getShapes(a, b); });
|
||||
|
||||
luax_pushtype(L, a);
|
||||
luax_pushtype(L, b);
|
||||
luax_pushshape(L, a);
|
||||
luax_pushshape(L, b);
|
||||
return 2;
|
||||
}
|
||||
|
||||
int w_Contact_getFixtures(lua_State *L)
|
||||
{
|
||||
luax_markdeprecated(L, 1, "Contact:getFixtures", API_METHOD, DEPRECATED_REPLACED, "Contact:getShapes");
|
||||
return w_Contact_getShapes(L);
|
||||
}
|
||||
|
||||
int w_Contact_isDestroyed(lua_State *L)
|
||||
{
|
||||
Contact *c = luax_checktype<Contact>(L, 1);
|
||||
@@ -174,8 +180,12 @@ static const luaL_Reg w_Contact_functions[] =
|
||||
{ "setTangentSpeed", w_Contact_setTangentSpeed },
|
||||
{ "getTangentSpeed", w_Contact_getTangentSpeed },
|
||||
{ "getChildren", w_Contact_getChildren },
|
||||
{ "getFixtures", w_Contact_getFixtures },
|
||||
{ "getShapes", w_Contact_getShapes },
|
||||
{ "isDestroyed", w_Contact_isDestroyed },
|
||||
|
||||
// Deprecated
|
||||
{ "getFixtures", w_Contact_getFixtures },
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ int w_EdgeShape_setNextVertex(lua_State *L)
|
||||
EdgeShape *t = luax_checkedgeshape(L, 1);
|
||||
float x = (float)luaL_checknumber(L, 2);
|
||||
float y = (float)luaL_checknumber(L, 3);
|
||||
t->setNextVertex(x, y);
|
||||
luax_catchexcept(L, [&]() { t->setNextVertex(x, y); });
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -46,14 +46,15 @@ int w_EdgeShape_setPreviousVertex(lua_State *L)
|
||||
EdgeShape *t = luax_checkedgeshape(L, 1);
|
||||
float x = (float)luaL_checknumber(L, 2);
|
||||
float y = (float)luaL_checknumber(L, 3);
|
||||
t->setPreviousVertex(x, y);
|
||||
luax_catchexcept(L, [&]() { t->setPreviousVertex(x, y); });
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_EdgeShape_getNextVertex(lua_State *L)
|
||||
{
|
||||
EdgeShape *t = luax_checkedgeshape(L, 1);
|
||||
b2Vec2 v = t->getNextVertex();
|
||||
b2Vec2 v;
|
||||
luax_catchexcept(L, [&]() { v = t->getNextVertex(); });
|
||||
lua_pushnumber(L, v.x);
|
||||
lua_pushnumber(L, v.y);
|
||||
return 2;
|
||||
@@ -62,7 +63,8 @@ int w_EdgeShape_getNextVertex(lua_State *L)
|
||||
int w_EdgeShape_getPreviousVertex(lua_State *L)
|
||||
{
|
||||
EdgeShape *t = luax_checkedgeshape(L, 1);
|
||||
b2Vec2 v = t->getPreviousVertex();
|
||||
b2Vec2 v;
|
||||
luax_catchexcept(L, [&]() { v = t->getPreviousVertex(); });
|
||||
lua_pushnumber(L, v.x);
|
||||
lua_pushnumber(L, v.y);
|
||||
return 2;
|
||||
@@ -72,7 +74,9 @@ int w_EdgeShape_getPoints(lua_State *L)
|
||||
{
|
||||
EdgeShape *t = luax_checkedgeshape(L, 1);
|
||||
lua_remove(L, 1);
|
||||
return t->getPoints(L);
|
||||
int ret = 0;
|
||||
luax_catchexcept(L, [&]() { ret = t->getPoints(L); });
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const luaL_Reg w_EdgeShape_functions[] =
|
||||
|
||||
@@ -1,311 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2023 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 "wrap_Fixture.h"
|
||||
#include "common/StringMap.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace physics
|
||||
{
|
||||
namespace box2d
|
||||
{
|
||||
|
||||
Fixture *luax_checkfixture(lua_State *L, int idx)
|
||||
{
|
||||
Fixture *f = luax_checktype<Fixture>(L, idx);
|
||||
if (!f->isValid())
|
||||
luaL_error(L, "Attempt to use destroyed fixture.");
|
||||
return f;
|
||||
}
|
||||
|
||||
int w_Fixture_getType(lua_State *L)
|
||||
{
|
||||
Fixture *t = luax_checkfixture(L, 1);
|
||||
const char *type = "";
|
||||
Shape::getConstant(t->getType(), type);
|
||||
lua_pushstring(L, type);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Fixture_setFriction(lua_State *L)
|
||||
{
|
||||
Fixture *t = luax_checkfixture(L, 1);
|
||||
float arg1 = (float)luaL_checknumber(L, 2);
|
||||
t->setFriction(arg1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_Fixture_setRestitution(lua_State *L)
|
||||
{
|
||||
Fixture *t = luax_checkfixture(L, 1);
|
||||
float arg1 = (float)luaL_checknumber(L, 2);
|
||||
t->setRestitution(arg1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_Fixture_setDensity(lua_State *L)
|
||||
{
|
||||
Fixture *t = luax_checkfixture(L, 1);
|
||||
float arg1 = (float)luaL_checknumber(L, 2);
|
||||
luax_catchexcept(L, [&](){ t->setDensity(arg1); });
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_Fixture_setSensor(lua_State *L)
|
||||
{
|
||||
Fixture *t = luax_checkfixture(L, 1);
|
||||
bool arg1 = luax_checkboolean(L, 2);
|
||||
t->setSensor(arg1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_Fixture_getFriction(lua_State *L)
|
||||
{
|
||||
Fixture *t = luax_checkfixture(L, 1);
|
||||
lua_pushnumber(L, t->getFriction());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Fixture_getRestitution(lua_State *L)
|
||||
{
|
||||
Fixture *t = luax_checkfixture(L, 1);
|
||||
lua_pushnumber(L, t->getRestitution());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Fixture_getDensity(lua_State *L)
|
||||
{
|
||||
Fixture *t = luax_checkfixture(L, 1);
|
||||
lua_pushnumber(L, t->getDensity());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Fixture_isSensor(lua_State *L)
|
||||
{
|
||||
Fixture *t = luax_checkfixture(L, 1);
|
||||
luax_pushboolean(L, t->isSensor());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Fixture_getBody(lua_State *L)
|
||||
{
|
||||
Fixture *t = luax_checkfixture(L, 1);
|
||||
Body *body = t->getBody();
|
||||
if (body == 0)
|
||||
return 0;
|
||||
luax_pushtype(L, body);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Fixture_getShape(lua_State *L)
|
||||
{
|
||||
Fixture *t = luax_checkfixture(L, 1);
|
||||
Shape * shape = t->getShape();
|
||||
if (shape == nullptr)
|
||||
return 0;
|
||||
switch (shape->getType())
|
||||
{
|
||||
case Shape::SHAPE_EDGE:
|
||||
luax_pushtype(L, dynamic_cast<EdgeShape *>(shape));
|
||||
break;
|
||||
case Shape::SHAPE_CHAIN:
|
||||
luax_pushtype(L, dynamic_cast<ChainShape *>(shape));
|
||||
break;
|
||||
case Shape::SHAPE_CIRCLE:
|
||||
luax_pushtype(L, dynamic_cast<CircleShape *>(shape));
|
||||
break;
|
||||
case Shape::SHAPE_POLYGON:
|
||||
luax_pushtype(L, dynamic_cast<PolygonShape *>(shape));
|
||||
break;
|
||||
default:
|
||||
luax_pushtype(L, shape);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Fixture_testPoint(lua_State *L)
|
||||
{
|
||||
Fixture *t = luax_checkfixture(L, 1);
|
||||
float x = (float)luaL_checknumber(L, 2);
|
||||
float y = (float)luaL_checknumber(L, 3);
|
||||
luax_pushboolean(L, t->testPoint(x, y));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Fixture_rayCast(lua_State *L)
|
||||
{
|
||||
Fixture *t = luax_checkfixture(L, 1);
|
||||
lua_remove(L, 1);
|
||||
int ret = 0;
|
||||
luax_catchexcept(L, [&](){ ret = t->rayCast(L); });
|
||||
return ret;
|
||||
}
|
||||
|
||||
int w_Fixture_setFilterData(lua_State *L)
|
||||
{
|
||||
Fixture *t = luax_checkfixture(L, 1);
|
||||
int v[3];
|
||||
v[0] = (int) luaL_checkinteger(L, 2);
|
||||
v[1] = (int) luaL_checkinteger(L, 3);
|
||||
v[2] = (int) luaL_checkinteger(L, 4);
|
||||
t->setFilterData(v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_Fixture_getFilterData(lua_State *L)
|
||||
{
|
||||
Fixture *t = luax_checkfixture(L, 1);
|
||||
int v[3];
|
||||
t->getFilterData(v);
|
||||
lua_pushinteger(L, v[0]);
|
||||
lua_pushinteger(L, v[1]);
|
||||
lua_pushinteger(L, v[2]);
|
||||
return 3;
|
||||
}
|
||||
|
||||
int w_Fixture_setCategory(lua_State *L)
|
||||
{
|
||||
Fixture *t = luax_checkfixture(L, 1);
|
||||
lua_remove(L, 1);
|
||||
return t->setCategory(L);
|
||||
}
|
||||
|
||||
int w_Fixture_getCategory(lua_State *L)
|
||||
{
|
||||
Fixture *t = luax_checkfixture(L, 1);
|
||||
lua_remove(L, 1);
|
||||
return t->getCategory(L);
|
||||
}
|
||||
|
||||
int w_Fixture_setMask(lua_State *L)
|
||||
{
|
||||
Fixture *t = luax_checkfixture(L, 1);
|
||||
lua_remove(L, 1);
|
||||
return t->setMask(L);
|
||||
}
|
||||
|
||||
int w_Fixture_getMask(lua_State *L)
|
||||
{
|
||||
Fixture *t = luax_checkfixture(L, 1);
|
||||
lua_remove(L, 1);
|
||||
return t->getMask(L);
|
||||
}
|
||||
|
||||
int w_Fixture_setUserData(lua_State *L)
|
||||
{
|
||||
Fixture *t = luax_checkfixture(L, 1);
|
||||
lua_remove(L, 1);
|
||||
return t->setUserData(L);
|
||||
}
|
||||
|
||||
int w_Fixture_getUserData(lua_State *L)
|
||||
{
|
||||
Fixture *t = luax_checkfixture(L, 1);
|
||||
lua_remove(L, 1);
|
||||
return t->getUserData(L);
|
||||
}
|
||||
|
||||
int w_Fixture_getBoundingBox(lua_State *L)
|
||||
{
|
||||
Fixture *t = luax_checkfixture(L, 1);
|
||||
lua_remove(L, 1);
|
||||
return t->getBoundingBox(L);
|
||||
}
|
||||
|
||||
int w_Fixture_getMassData(lua_State *L)
|
||||
{
|
||||
Fixture *t = luax_checkfixture(L, 1);
|
||||
lua_remove(L, 1);
|
||||
return t->getMassData(L);
|
||||
}
|
||||
|
||||
int w_Fixture_getGroupIndex(lua_State *L)
|
||||
{
|
||||
Fixture *t = luax_checkfixture(L, 1);
|
||||
int i = t->getGroupIndex();
|
||||
lua_pushinteger(L, i);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Fixture_setGroupIndex(lua_State *L)
|
||||
{
|
||||
Fixture *t = luax_checkfixture(L, 1);
|
||||
int i = (int) luaL_checkinteger(L, 2);
|
||||
t->setGroupIndex(i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_Fixture_destroy(lua_State *L)
|
||||
{
|
||||
Fixture *t = luax_checkfixture(L, 1);
|
||||
luax_catchexcept(L, [&](){ t->destroy(); });
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_Fixture_isDestroyed(lua_State *L)
|
||||
{
|
||||
Fixture *f = luax_checktype<Fixture>(L, 1);
|
||||
luax_pushboolean(L, !f->isValid());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg w_Fixture_functions[] =
|
||||
{
|
||||
{ "getType", w_Fixture_getType },
|
||||
{ "setFriction", w_Fixture_setFriction },
|
||||
{ "setRestitution", w_Fixture_setRestitution },
|
||||
{ "setDensity", w_Fixture_setDensity },
|
||||
{ "setSensor", w_Fixture_setSensor },
|
||||
{ "getFriction", w_Fixture_getFriction },
|
||||
{ "getRestitution", w_Fixture_getRestitution },
|
||||
{ "getDensity", w_Fixture_getDensity },
|
||||
{ "getBody", w_Fixture_getBody },
|
||||
{ "getShape", w_Fixture_getShape },
|
||||
{ "isSensor", w_Fixture_isSensor },
|
||||
{ "testPoint", w_Fixture_testPoint },
|
||||
{ "rayCast", w_Fixture_rayCast },
|
||||
{ "setFilterData", w_Fixture_setFilterData },
|
||||
{ "getFilterData", w_Fixture_getFilterData },
|
||||
{ "setCategory", w_Fixture_setCategory },
|
||||
{ "getCategory", w_Fixture_getCategory },
|
||||
{ "setMask", w_Fixture_setMask },
|
||||
{ "getMask", w_Fixture_getMask },
|
||||
{ "setUserData", w_Fixture_setUserData },
|
||||
{ "getUserData", w_Fixture_getUserData },
|
||||
{ "getBoundingBox", w_Fixture_getBoundingBox },
|
||||
{ "getMassData", w_Fixture_getMassData },
|
||||
{ "getGroupIndex", w_Fixture_getGroupIndex },
|
||||
{ "setGroupIndex", w_Fixture_setGroupIndex },
|
||||
{ "destroy", w_Fixture_destroy },
|
||||
{ "isDestroyed", w_Fixture_isDestroyed },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
extern "C" int luaopen_fixture(lua_State *L)
|
||||
{
|
||||
return luax_register_type(L, &Fixture::type, w_Fixture_functions, nullptr);
|
||||
}
|
||||
|
||||
} // box2d
|
||||
} // physics
|
||||
} // love
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2023 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.
|
||||
**/
|
||||
|
||||
#ifndef LOVE_PHYSICS_BOX2D_WRAP_FIXTURE_H
|
||||
#define LOVE_PHYSICS_BOX2D_WRAP_FIXTURE_H
|
||||
|
||||
// LOVE
|
||||
#include "common/runtime.h"
|
||||
#include "Fixture.h"
|
||||
#include "wrap_Physics.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace physics
|
||||
{
|
||||
namespace box2d
|
||||
{
|
||||
|
||||
Fixture *luax_checkfixture(lua_State *L, int idx);
|
||||
extern "C" int luaopen_fixture(lua_State *L);
|
||||
|
||||
} // box2d
|
||||
} // physics
|
||||
} // love
|
||||
|
||||
#endif // LOVE_PHYSICS_BOX2D_WRAP_FIXTURE_H
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "wrap_World.h"
|
||||
#include "wrap_Contact.h"
|
||||
#include "wrap_Body.h"
|
||||
#include "wrap_Fixture.h"
|
||||
#include "wrap_Shape.h"
|
||||
#include "wrap_CircleShape.h"
|
||||
#include "wrap_PolygonShape.h"
|
||||
@@ -83,38 +82,225 @@ int w_newBody(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_newCircleBody(lua_State *L)
|
||||
{
|
||||
World *world = luax_checkworld(L, 1);
|
||||
|
||||
const char *typestr = luaL_checkstring(L, 2);
|
||||
Body::Type btype = Body::BODY_STATIC;
|
||||
if (!Body::getConstant(typestr, btype))
|
||||
return luax_enumerror(L, "Body type", Body::getConstants(btype), typestr);
|
||||
|
||||
float x = (float)luaL_checknumber(L, 3);
|
||||
float y = (float)luaL_checknumber(L, 4);
|
||||
float radius = (float)luaL_checknumber(L, 5);
|
||||
|
||||
Body *body = nullptr;
|
||||
luax_catchexcept(L, [&]() { body = instance()->newCircleBody(world, btype, x, y, radius); });
|
||||
|
||||
luax_pushtype(L, body);
|
||||
body->release();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_newRectangleBody(lua_State *L)
|
||||
{
|
||||
World *world = luax_checkworld(L, 1);
|
||||
|
||||
const char *typestr = luaL_checkstring(L, 2);
|
||||
Body::Type btype = Body::BODY_STATIC;
|
||||
if (!Body::getConstant(typestr, btype))
|
||||
return luax_enumerror(L, "Body type", Body::getConstants(btype), typestr);
|
||||
|
||||
float x = (float)luaL_checknumber(L, 3);
|
||||
float y = (float)luaL_checknumber(L, 4);
|
||||
float w = (float)luaL_checknumber(L, 5);
|
||||
float h = (float)luaL_checknumber(L, 6);
|
||||
float angle = (float)luaL_optnumber(L, 7, 0.0);
|
||||
|
||||
Body *body = nullptr;
|
||||
luax_catchexcept(L, [&]() { body = instance()->newRectangleBody(world, btype, x, y, w, h, angle); });
|
||||
|
||||
luax_pushtype(L, body);
|
||||
body->release();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_newPolygonBody(lua_State *L)
|
||||
{
|
||||
World *world = luax_checkworld(L, 1);
|
||||
|
||||
const char *typestr = luaL_checkstring(L, 2);
|
||||
Body::Type btype = Body::BODY_STATIC;
|
||||
if (!Body::getConstant(typestr, btype))
|
||||
return luax_enumerror(L, "Body type", Body::getConstants(btype), typestr);
|
||||
|
||||
int argc = lua_gettop(L);
|
||||
|
||||
bool istable = lua_istable(L, 3);
|
||||
if (istable)
|
||||
argc = (int)luax_objlen(L, 3);
|
||||
|
||||
if (argc % 2 != 0)
|
||||
return luaL_error(L, "Number of vertex components must be a multiple of two.");
|
||||
|
||||
int vcount = argc / 2;
|
||||
std::vector<Vector2> coords;
|
||||
|
||||
if (istable)
|
||||
{
|
||||
for (int i = 0; i < vcount; i++)
|
||||
{
|
||||
lua_rawgeti(L, 3, 1 + i * 2);
|
||||
lua_rawgeti(L, 3, 2 + i * 2);
|
||||
float x = (float)luaL_checknumber(L, -2);
|
||||
float y = (float)luaL_checknumber(L, -1);
|
||||
coords.emplace_back(x, y);
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < vcount; i++)
|
||||
{
|
||||
float x = (float)luaL_checknumber(L, 3 + i * 2);
|
||||
float y = (float)luaL_checknumber(L, 4 + i * 2);
|
||||
coords.emplace_back(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
Body *body = nullptr;
|
||||
luax_catchexcept(L, [&]() { body = instance()->newPolygonBody(world, btype, coords.data(), (int)coords.size()); });
|
||||
|
||||
luax_pushtype(L, body);
|
||||
body->release();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_newEdgeBody(lua_State *L)
|
||||
{
|
||||
World *world = luax_checkworld(L, 1);
|
||||
|
||||
const char *typestr = luaL_checkstring(L, 2);
|
||||
Body::Type btype = Body::BODY_STATIC;
|
||||
if (!Body::getConstant(typestr, btype))
|
||||
return luax_enumerror(L, "Body type", Body::getConstants(btype), typestr);
|
||||
|
||||
float x1 = (float)luaL_checknumber(L, 3);
|
||||
float y1 = (float)luaL_checknumber(L, 4);
|
||||
float x2 = (float)luaL_checknumber(L, 5);
|
||||
float y2 = (float)luaL_checknumber(L, 6);
|
||||
bool oneSided = luax_optboolean(L, 7, false);
|
||||
|
||||
Body *body = nullptr;
|
||||
luax_catchexcept(L, [&]() { body = instance()->newEdgeBody(world, btype, x1, y1, x2, y2, oneSided); });
|
||||
|
||||
luax_pushtype(L, body);
|
||||
body->release();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_newChainBody(lua_State *L)
|
||||
{
|
||||
World *world = luax_checkworld(L, 1);
|
||||
|
||||
const char *typestr = luaL_checkstring(L, 2);
|
||||
Body::Type btype = Body::BODY_STATIC;
|
||||
if (!Body::getConstant(typestr, btype))
|
||||
return luax_enumerror(L, "Body type", Body::getConstants(btype), typestr);
|
||||
|
||||
bool loop = luax_checkboolean(L, 3);
|
||||
|
||||
int argc = lua_gettop(L) - 3;
|
||||
|
||||
bool istable = lua_istable(L, 4);
|
||||
if (istable)
|
||||
argc = (int)luax_objlen(L, 4);
|
||||
|
||||
if (argc == 0 || argc % 2 != 0)
|
||||
return luaL_error(L, "Number of vertex components must be a multiple of two.");
|
||||
|
||||
int vcount = argc / 2;
|
||||
std::vector<Vector2> coords;
|
||||
|
||||
if (istable)
|
||||
{
|
||||
for (int i = 0; i < vcount; i++)
|
||||
{
|
||||
lua_rawgeti(L, 4, 1 + i * 2);
|
||||
lua_rawgeti(L, 4, 2 + i * 2);
|
||||
float x = (float)lua_tonumber(L, -2);
|
||||
float y = (float)lua_tonumber(L, -1);
|
||||
coords.emplace_back(x, y);
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < vcount; i++)
|
||||
{
|
||||
float x = (float)luaL_checknumber(L, 4 + i * 2);
|
||||
float y = (float)luaL_checknumber(L, 5 + i * 2);
|
||||
coords.emplace_back(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
Body *body = nullptr;
|
||||
luax_catchexcept(L, [&]() { body = instance()->newChainBody(world, btype, loop, coords.data(), (int)coords.size()); });
|
||||
|
||||
luax_pushtype(L, body);
|
||||
body->release();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_newFixture(lua_State *L)
|
||||
{
|
||||
luax_markdeprecated(L, 1, "love.physics.newFixture", API_FUNCTION, DEPRECATED_REPLACED, "love.physics.newCircle/Rectangle/Polygon/Edge/ChainShape");
|
||||
|
||||
Body *body = luax_checkbody(L, 1);
|
||||
Shape *shape = luax_checkshape(L, 2);
|
||||
float density = (float)luaL_optnumber(L, 3, 1.0f);
|
||||
Fixture *fixture;
|
||||
luax_catchexcept(L, [&](){ fixture = instance()->newFixture(body, shape, density); });
|
||||
luax_pushtype(L, fixture);
|
||||
fixture->release();
|
||||
|
||||
Shape *newShape;
|
||||
luax_catchexcept(L, [&]() { newShape = instance()->newAttachedShape(body, shape, density); });
|
||||
|
||||
luax_pushshape(L, newShape);
|
||||
newShape->release();
|
||||
return 1;
|
||||
}
|
||||
|
||||
static Body *luax_optbodyforshape(lua_State *L, int idx, const char *name)
|
||||
{
|
||||
if (lua_isnoneornil(L, idx) || luax_istype(L, idx, Object::type))
|
||||
return luax_checkbody(L, idx);
|
||||
|
||||
luax_markdeprecated(L, 1, name, API_FUNCTION_VARIANT, DEPRECATED_REPLACED, "variant with Body parameter");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int w_newCircleShape(lua_State *L)
|
||||
{
|
||||
int top = lua_gettop(L);
|
||||
Body *body = luax_optbodyforshape(L, 1, "love.physics.newCircleShape");
|
||||
int bodyidx = body ? 1 : 0;
|
||||
|
||||
int top = lua_gettop(L) - bodyidx;
|
||||
|
||||
if (top == 1)
|
||||
{
|
||||
float radius = (float)luaL_checknumber(L, 1);
|
||||
float radius = (float)luaL_checknumber(L, bodyidx + 1);
|
||||
CircleShape *shape;
|
||||
luax_catchexcept(L, [&](){ shape = instance()->newCircleShape(radius); });
|
||||
luax_catchexcept(L, [&](){ shape = instance()->newCircleShape(body, 0, 0, radius); });
|
||||
luax_pushtype(L, shape);
|
||||
shape->release();
|
||||
return 1;
|
||||
}
|
||||
else if (top == 3)
|
||||
{
|
||||
float x = (float)luaL_checknumber(L, 1);
|
||||
float y = (float)luaL_checknumber(L, 2);
|
||||
float radius = (float)luaL_checknumber(L, 3);
|
||||
float x = (float)luaL_checknumber(L, bodyidx + 1);
|
||||
float y = (float)luaL_checknumber(L, bodyidx + 2);
|
||||
float radius = (float)luaL_checknumber(L, bodyidx + 3);
|
||||
CircleShape *shape;
|
||||
luax_catchexcept(L, [&](){ shape = instance()->newCircleShape(x, y, radius); });
|
||||
luax_catchexcept(L, [&](){ shape = instance()->newCircleShape(body, x, y, radius); });
|
||||
luax_pushtype(L, shape);
|
||||
shape->release();
|
||||
return 1;
|
||||
@@ -125,27 +311,30 @@ int w_newCircleShape(lua_State *L)
|
||||
|
||||
int w_newRectangleShape(lua_State *L)
|
||||
{
|
||||
int top = lua_gettop(L);
|
||||
Body *body = luax_optbodyforshape(L, 1, "love.physics.newRectangleShape");
|
||||
int bodyidx = body ? 1 : 0;
|
||||
|
||||
int top = lua_gettop(L) - bodyidx;
|
||||
|
||||
if (top == 2)
|
||||
{
|
||||
float w = (float)luaL_checknumber(L, 1);
|
||||
float h = (float)luaL_checknumber(L, 2);
|
||||
float w = (float)luaL_checknumber(L, bodyidx + 1);
|
||||
float h = (float)luaL_checknumber(L, bodyidx + 2);
|
||||
PolygonShape *shape;
|
||||
luax_catchexcept(L, [&](){ shape = instance()->newRectangleShape(w, h); });
|
||||
luax_catchexcept(L, [&](){ shape = instance()->newRectangleShape(body, 0, 0, w, h, 0); });
|
||||
luax_pushtype(L, shape);
|
||||
shape->release();
|
||||
return 1;
|
||||
}
|
||||
else if (top == 4 || top == 5)
|
||||
{
|
||||
float x = (float)luaL_checknumber(L, 1);
|
||||
float y = (float)luaL_checknumber(L, 2);
|
||||
float w = (float)luaL_checknumber(L, 3);
|
||||
float h = (float)luaL_checknumber(L, 4);
|
||||
float angle = (float)luaL_optnumber(L, 5, 0);
|
||||
float x = (float)luaL_checknumber(L, bodyidx + 1);
|
||||
float y = (float)luaL_checknumber(L, bodyidx + 2);
|
||||
float w = (float)luaL_checknumber(L, bodyidx + 3);
|
||||
float h = (float)luaL_checknumber(L, bodyidx + 4);
|
||||
float angle = (float)luaL_optnumber(L, bodyidx + 5, 0);
|
||||
PolygonShape *shape;
|
||||
luax_catchexcept(L, [&](){ shape = instance()->newRectangleShape(x, y, w, h, angle); });
|
||||
luax_catchexcept(L, [&](){ shape = instance()->newRectangleShape(body, x, y, w, h, angle); });
|
||||
luax_pushtype(L, shape);
|
||||
shape->release();
|
||||
return 1;
|
||||
@@ -156,13 +345,16 @@ int w_newRectangleShape(lua_State *L)
|
||||
|
||||
int w_newEdgeShape(lua_State *L)
|
||||
{
|
||||
float x1 = (float)luaL_checknumber(L, 1);
|
||||
float y1 = (float)luaL_checknumber(L, 2);
|
||||
float x2 = (float)luaL_checknumber(L, 3);
|
||||
float y2 = (float)luaL_checknumber(L, 4);
|
||||
bool oneSided = luax_optboolean(L, 5, false);
|
||||
Body *body = luax_optbodyforshape(L, 1, "love.physics.newEdgeShape");
|
||||
int bodyidx = body ? 1 : 0;
|
||||
|
||||
float x1 = (float)luaL_checknumber(L, bodyidx + 1);
|
||||
float y1 = (float)luaL_checknumber(L, bodyidx + 2);
|
||||
float x2 = (float)luaL_checknumber(L, bodyidx + 3);
|
||||
float y2 = (float)luaL_checknumber(L, bodyidx + 4);
|
||||
bool oneSided = luax_optboolean(L, bodyidx + 5, false);
|
||||
EdgeShape *shape;
|
||||
luax_catchexcept(L, [&](){ shape = instance()->newEdgeShape(x1, y1, x2, y2, oneSided); });
|
||||
luax_catchexcept(L, [&](){ shape = instance()->newEdgeShape(body, x1, y1, x2, y2, oneSided); });
|
||||
luax_pushtype(L, shape);
|
||||
shape->release();
|
||||
return 1;
|
||||
@@ -170,16 +362,97 @@ int w_newEdgeShape(lua_State *L)
|
||||
|
||||
int w_newPolygonShape(lua_State *L)
|
||||
{
|
||||
int ret = 0;
|
||||
luax_catchexcept(L, [&](){ ret = instance()->newPolygonShape(L); });
|
||||
return ret;
|
||||
Body *body = luax_optbodyforshape(L, 1, "love.physics.newPolygonShape");
|
||||
int bodyidx = body ? 1 : 0;
|
||||
|
||||
int argc = lua_gettop(L) - bodyidx;
|
||||
|
||||
bool istable = lua_istable(L, bodyidx + 1);
|
||||
|
||||
if (istable)
|
||||
argc = (int)luax_objlen(L, bodyidx + 1);
|
||||
|
||||
if (argc % 2 != 0)
|
||||
return luaL_error(L, "Number of vertex components must be a multiple of two.");
|
||||
|
||||
int vcount = argc / 2;
|
||||
std::vector<Vector2> coords;
|
||||
|
||||
if (istable)
|
||||
{
|
||||
for (int i = 0; i < vcount; i++)
|
||||
{
|
||||
lua_rawgeti(L, bodyidx + 1, 1 + i * 2);
|
||||
lua_rawgeti(L, bodyidx + 1, 2 + i * 2);
|
||||
float x = (float)luaL_checknumber(L, -2);
|
||||
float y = (float)luaL_checknumber(L, -1);
|
||||
coords.emplace_back(x, y);
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < vcount; i++)
|
||||
{
|
||||
float x = (float)luaL_checknumber(L, bodyidx + 1 + i * 2);
|
||||
float y = (float)luaL_checknumber(L, bodyidx + 2 + i * 2);
|
||||
coords.emplace_back(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
PolygonShape *shape = nullptr;
|
||||
luax_catchexcept(L, [&](){ shape = instance()->newPolygonShape(body, coords.data(), (int)coords.size()); });
|
||||
luax_pushtype(L, shape);
|
||||
shape->release();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_newChainShape(lua_State *L)
|
||||
{
|
||||
int ret = 0;
|
||||
luax_catchexcept(L, [&](){ ret = instance()->newChainShape(L); });
|
||||
return ret;
|
||||
Body *body = luax_optbodyforshape(L, 1, "love.physics.newChainShape");
|
||||
int bodyidx = body ? 1 : 0;
|
||||
|
||||
int argc = lua_gettop(L) - 1 - bodyidx; // first argument is looping
|
||||
|
||||
bool istable = lua_istable(L, bodyidx + 2);
|
||||
|
||||
if (istable)
|
||||
argc = (int)luax_objlen(L, bodyidx + 2);
|
||||
|
||||
if (argc == 0 || argc % 2 != 0)
|
||||
return luaL_error(L, "Number of vertex components must be a multiple of two.");
|
||||
|
||||
int vcount = argc / 2;
|
||||
bool loop = luax_checkboolean(L, bodyidx + 1);
|
||||
std::vector<Vector2> coords;
|
||||
|
||||
if (istable)
|
||||
{
|
||||
for (int i = 0; i < vcount; i++)
|
||||
{
|
||||
lua_rawgeti(L, bodyidx + 2, 1 + i * 2);
|
||||
lua_rawgeti(L, bodyidx + 2, 2 + i * 2);
|
||||
float x = (float)lua_tonumber(L, -2);
|
||||
float y = (float)lua_tonumber(L, -1);
|
||||
coords.emplace_back(x, y);
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < vcount; i++)
|
||||
{
|
||||
float x = (float)luaL_checknumber(L, bodyidx + 2 + i * 2);
|
||||
float y = (float)luaL_checknumber(L, bodyidx + 3 + i * 2);
|
||||
coords.emplace_back(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
ChainShape *shape = nullptr;
|
||||
luax_catchexcept(L, [&]() { shape = instance()->newChainShape(body, loop, coords.data(), coords.size()); });
|
||||
luax_pushtype(L, shape);
|
||||
shape->release();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_newDistanceJoint(lua_State *L)
|
||||
@@ -573,7 +846,11 @@ static const luaL_Reg functions[] =
|
||||
{
|
||||
{ "newWorld", w_newWorld },
|
||||
{ "newBody", w_newBody },
|
||||
{ "newFixture", w_newFixture },
|
||||
{ "newCircleBody", w_newCircleBody },
|
||||
{ "newRectangleBody", w_newRectangleBody },
|
||||
{ "newPolygonBody", w_newPolygonBody },
|
||||
{ "newEdgeBody", w_newEdgeBody },
|
||||
{ "newChainBody", w_newChainBody },
|
||||
{ "newCircleShape", w_newCircleShape },
|
||||
{ "newRectangleShape", w_newRectangleShape },
|
||||
{ "newPolygonShape", w_newPolygonShape },
|
||||
@@ -597,6 +874,10 @@ static const luaL_Reg functions[] =
|
||||
{ "computeLinearFrequency", w_computeLinearFrequency },
|
||||
{ "computeAngularStiffness", w_computeAngularStiffness },
|
||||
{ "computeAngularFrequency", w_computeAngularFrequency },
|
||||
|
||||
// Deprecated
|
||||
{ "newFixture", w_newFixture },
|
||||
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
@@ -605,7 +886,6 @@ static const lua_CFunction types[] =
|
||||
luaopen_world,
|
||||
luaopen_contact,
|
||||
luaopen_body,
|
||||
luaopen_fixture,
|
||||
luaopen_shape,
|
||||
luaopen_circleshape,
|
||||
luaopen_polygonshape,
|
||||
|
||||
@@ -36,13 +36,17 @@ int w_PolygonShape_getPoints(lua_State *L)
|
||||
{
|
||||
PolygonShape *t = luax_checkpolygonshape(L, 1);
|
||||
lua_remove(L, 1);
|
||||
return t->getPoints(L);
|
||||
int ret = 0;
|
||||
luax_catchexcept(L, [&]() { ret = t->getPoints(L); });
|
||||
return ret;
|
||||
}
|
||||
|
||||
int w_PolygonShape_validate(lua_State *L)
|
||||
{
|
||||
PolygonShape *t = luax_checkpolygonshape(L, 1);
|
||||
luax_pushboolean(L, t->validate());
|
||||
bool valid = false;
|
||||
luax_catchexcept(L, [&]() { valid = t->validate(); });
|
||||
luax_pushboolean(L, valid);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,35 @@ Shape *luax_checkshape(lua_State *L, int idx)
|
||||
return luax_checktype<Shape>(L, idx);
|
||||
}
|
||||
|
||||
void luax_pushshape(lua_State *L, Shape *shape)
|
||||
{
|
||||
if (shape != nullptr)
|
||||
{
|
||||
switch (shape->getType())
|
||||
{
|
||||
case Shape::SHAPE_CIRCLE:
|
||||
luax_pushtype(L, (CircleShape *) shape);
|
||||
break;
|
||||
case Shape::SHAPE_POLYGON:
|
||||
luax_pushtype(L, (PolygonShape *) shape);
|
||||
break;
|
||||
case Shape::SHAPE_EDGE:
|
||||
luax_pushtype(L, (EdgeShape *) shape);
|
||||
break;
|
||||
case Shape::SHAPE_CHAIN:
|
||||
luax_pushtype(L, (ChainShape *) shape);
|
||||
break;
|
||||
default:
|
||||
luax_pushtype(L, shape);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lua_pushnil(L);
|
||||
}
|
||||
}
|
||||
|
||||
int w_Shape_getType(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
@@ -45,7 +74,8 @@ int w_Shape_getType(lua_State *L)
|
||||
int w_Shape_getRadius(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
float radius = t->getRadius();
|
||||
float radius = 0;
|
||||
luax_catchexcept(L, [&]() { radius = t->getRadius(); });
|
||||
lua_pushnumber(L, radius);
|
||||
return 1;
|
||||
}
|
||||
@@ -53,20 +83,115 @@ int w_Shape_getRadius(lua_State *L)
|
||||
int w_Shape_getChildCount(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
int childCount = t->getChildCount();
|
||||
int childCount = 0;
|
||||
luax_catchexcept(L, [&]() { childCount = t->getChildCount(); });
|
||||
lua_pushinteger(L, childCount);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Shape_setFriction(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
float arg1 = (float)luaL_checknumber(L, 2);
|
||||
luax_catchexcept(L, [&]() { t->setFriction(arg1); });
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_Shape_setRestitution(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
float arg1 = (float)luaL_checknumber(L, 2);
|
||||
luax_catchexcept(L, [&]() { t->setRestitution(arg1); });
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_Shape_setDensity(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
float arg1 = (float)luaL_checknumber(L, 2);
|
||||
luax_catchexcept(L, [&](){ t->setDensity(arg1); });
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_Shape_setSensor(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
bool arg1 = luax_checkboolean(L, 2);
|
||||
luax_catchexcept(L, [&]() { t->setSensor(arg1); });
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_Shape_getFriction(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
float friction = 0;
|
||||
luax_catchexcept(L, [&]() { friction = t->getFriction(); });
|
||||
lua_pushnumber(L, friction);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Shape_getRestitution(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
float r = 0;
|
||||
luax_catchexcept(L, [&]() { r = t->getRestitution(); });
|
||||
lua_pushnumber(L, r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Shape_getDensity(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
float d = 0;
|
||||
luax_catchexcept(L, [&]() { d = t->getDensity(); });
|
||||
lua_pushnumber(L, d);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Shape_isSensor(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
bool sensor = false;
|
||||
luax_catchexcept(L, [&]() { sensor = t->isSensor(); });
|
||||
luax_pushboolean(L, sensor);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Shape_getBody(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
Body *body = t->getBody();
|
||||
if (body == nullptr)
|
||||
return 0;
|
||||
luax_pushtype(L, body);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Shape_getShape(lua_State *L)
|
||||
{
|
||||
luax_markdeprecated(L, 1, "Fixture:getShape", API_METHOD, DEPRECATED_NO_REPLACEMENT, nullptr);
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
luax_pushshape(L, t);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Shape_testPoint(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
float x = (float)luaL_checknumber(L, 2);
|
||||
float y = (float)luaL_checknumber(L, 3);
|
||||
float r = (float)luaL_checknumber(L, 4);
|
||||
float px = (float)luaL_checknumber(L, 5);
|
||||
float py = (float)luaL_checknumber(L, 6);
|
||||
bool result = t->testPoint(x, y, r, px, py);
|
||||
bool result = false;
|
||||
if (!lua_isnoneornil(L, 4))
|
||||
{
|
||||
float r = (float)luaL_checknumber(L, 4);
|
||||
float px = (float)luaL_checknumber(L, 5);
|
||||
float py = (float)luaL_checknumber(L, 6);
|
||||
result = luax_catchexcept(L, [&]() { t->testPoint(x, y, r, px, py); });
|
||||
}
|
||||
else
|
||||
{
|
||||
result = luax_catchexcept(L, [&]() { t->testPoint(x, y); });
|
||||
}
|
||||
lua_pushboolean(L, result);
|
||||
return 1;
|
||||
}
|
||||
@@ -84,14 +209,143 @@ int w_Shape_computeAABB(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
lua_remove(L, 1);
|
||||
return t->computeAABB(L);
|
||||
int ret = 0;
|
||||
luax_catchexcept(L, [&]() { ret = t->computeAABB(L); });
|
||||
return ret;
|
||||
}
|
||||
|
||||
int w_Shape_computeMass(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
lua_remove(L, 1);
|
||||
return t->computeMass(L);
|
||||
int ret = 0;
|
||||
luax_catchexcept(L, [&]() { ret = t->computeMass(L); });
|
||||
return ret;
|
||||
}
|
||||
|
||||
int w_Shape_setFilterData(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
int v[3];
|
||||
v[0] = (int) luaL_checkinteger(L, 2);
|
||||
v[1] = (int) luaL_checkinteger(L, 3);
|
||||
v[2] = (int) luaL_checkinteger(L, 4);
|
||||
luax_catchexcept(L, [&]() { t->setFilterData(v); });
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_Shape_getFilterData(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
int v[3];
|
||||
luax_catchexcept(L, [&]() { t->getFilterData(v); });
|
||||
lua_pushinteger(L, v[0]);
|
||||
lua_pushinteger(L, v[1]);
|
||||
lua_pushinteger(L, v[2]);
|
||||
return 3;
|
||||
}
|
||||
|
||||
int w_Shape_setCategory(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
lua_remove(L, 1);
|
||||
int ret = 0;
|
||||
luax_catchexcept(L, [&]() { ret = t->setCategory(L); });
|
||||
return ret;
|
||||
}
|
||||
|
||||
int w_Shape_getCategory(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
lua_remove(L, 1);
|
||||
int ret = 0;
|
||||
luax_catchexcept(L, [&]() { ret = t->getCategory(L); });
|
||||
return ret;
|
||||
}
|
||||
|
||||
int w_Shape_setMask(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
lua_remove(L, 1);
|
||||
int ret = 0;
|
||||
luax_catchexcept(L, [&]() { ret = t->setMask(L); });
|
||||
return ret;
|
||||
}
|
||||
|
||||
int w_Shape_getMask(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
lua_remove(L, 1);
|
||||
int ret = 0;
|
||||
luax_catchexcept(L, [&]() { ret = t->getMask(L); });
|
||||
return ret;
|
||||
}
|
||||
|
||||
int w_Shape_setUserData(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
lua_remove(L, 1);
|
||||
int ret = 0;
|
||||
luax_catchexcept(L, [&]() { ret = t->setUserData(L); });
|
||||
return ret;
|
||||
}
|
||||
|
||||
int w_Shape_getUserData(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
lua_remove(L, 1);
|
||||
int ret = 0;
|
||||
luax_catchexcept(L, [&]() { ret = t->getUserData(L); });
|
||||
return ret;
|
||||
}
|
||||
|
||||
int w_Shape_getBoundingBox(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
lua_remove(L, 1);
|
||||
int ret = 0;
|
||||
luax_catchexcept(L, [&]() { ret = t->getBoundingBox(L); });
|
||||
return ret;
|
||||
}
|
||||
|
||||
int w_Shape_getMassData(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
lua_remove(L, 1);
|
||||
int ret = 0;
|
||||
luax_catchexcept(L, [&]() { ret = t->getMassData(L); });
|
||||
return ret;
|
||||
}
|
||||
|
||||
int w_Shape_getGroupIndex(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
int i = 0;
|
||||
luax_catchexcept(L, [&]() { i = t->getGroupIndex(); });
|
||||
lua_pushinteger(L, i);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_Shape_setGroupIndex(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
int i = (int) luaL_checkinteger(L, 2);
|
||||
luax_catchexcept(L, [&]() { t->setGroupIndex(i); });
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_Shape_destroy(lua_State *L)
|
||||
{
|
||||
Shape *t = luax_checkshape(L, 1);
|
||||
luax_catchexcept(L, [&](){ t->destroy(); });
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_Shape_isDestroyed(lua_State *L)
|
||||
{
|
||||
Shape *f = luax_checktype<Shape>(L, 1);
|
||||
luax_pushboolean(L, !f->isValid());
|
||||
return 1;
|
||||
}
|
||||
|
||||
const luaL_Reg w_Shape_functions[] =
|
||||
@@ -99,10 +353,33 @@ const luaL_Reg w_Shape_functions[] =
|
||||
{ "getType", w_Shape_getType },
|
||||
{ "getRadius", w_Shape_getRadius },
|
||||
{ "getChildCount", w_Shape_getChildCount },
|
||||
{ "setFriction", w_Shape_setFriction },
|
||||
{ "setRestitution", w_Shape_setRestitution },
|
||||
{ "setDensity", w_Shape_setDensity },
|
||||
{ "setSensor", w_Shape_setSensor },
|
||||
{ "getFriction", w_Shape_getFriction },
|
||||
{ "getRestitution", w_Shape_getRestitution },
|
||||
{ "getDensity", w_Shape_getDensity },
|
||||
{ "getBody", w_Shape_getBody },
|
||||
{ "isSensor", w_Shape_isSensor },
|
||||
{ "testPoint", w_Shape_testPoint },
|
||||
{ "rayCast", w_Shape_rayCast },
|
||||
{ "computeAABB", w_Shape_computeAABB },
|
||||
{ "computeMass", w_Shape_computeMass },
|
||||
{ "setFilterData", w_Shape_setFilterData },
|
||||
{ "getFilterData", w_Shape_getFilterData },
|
||||
{ "setCategory", w_Shape_setCategory },
|
||||
{ "getCategory", w_Shape_getCategory },
|
||||
{ "setMask", w_Shape_setMask },
|
||||
{ "getMask", w_Shape_getMask },
|
||||
{ "setUserData", w_Shape_setUserData },
|
||||
{ "getUserData", w_Shape_getUserData },
|
||||
{ "getBoundingBox", w_Shape_getBoundingBox },
|
||||
{ "getMassData", w_Shape_getMassData },
|
||||
{ "getGroupIndex", w_Shape_getGroupIndex },
|
||||
{ "setGroupIndex", w_Shape_setGroupIndex },
|
||||
{ "destroy", w_Shape_destroy },
|
||||
{ "isDestroyed", w_Shape_isDestroyed },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user