mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Merge remote-tracking branch 'offical/master'
This commit is contained in:
Vendored
+13
-13
@@ -22,17 +22,17 @@ VERSION_MAJOR :: u8(1)
|
||||
VERSION_MINOR :: u8(3)
|
||||
VERSION_PATCH :: u8(17)
|
||||
|
||||
VERSION_CREATE :: #force_inline proc(major, minor, patch: u8) -> u32 {
|
||||
VERSION_CREATE :: #force_inline proc "contextless" (major, minor, patch: u8) -> u32 {
|
||||
return (u32(major) << 16) | (u32(minor) << 8) | u32(patch)
|
||||
}
|
||||
|
||||
VERSION_GET_MAJOR :: #force_inline proc(version: u32) -> u8 {
|
||||
VERSION_GET_MAJOR :: #force_inline proc "contextless" (version: u32) -> u8 {
|
||||
return u8((version >> 16) & 0xff)
|
||||
}
|
||||
VERSION_GET_MINOR :: #force_inline proc(version: u32) -> u8 {
|
||||
VERSION_GET_MINOR :: #force_inline proc "contextless" (version: u32) -> u8 {
|
||||
return u8((version >> 8) & 0xff)
|
||||
}
|
||||
VERSION_GET_PATCH :: #force_inline proc(version: u32) -> u8 {
|
||||
VERSION_GET_PATCH :: #force_inline proc "contextless" (version: u32) -> u8 {
|
||||
return u8(version & 0xff)
|
||||
}
|
||||
|
||||
@@ -44,19 +44,19 @@ VERSION :: (u32(VERSION_MAJOR) << 16) | (u32(VERSION_MINOR) << 8) | u32(VERSION_
|
||||
// Network byte order is always Big Endian. Instead of using the method ENet
|
||||
// uses (leveraging {n,h}to{n,h}{s,l}), we can just use Odin's endianess types
|
||||
// to get the correct byte swaps, if any.
|
||||
HOST_TO_NET_16 :: #force_inline proc(value: u16) -> u16 {
|
||||
HOST_TO_NET_16 :: #force_inline proc "contextless" (value: u16) -> u16 {
|
||||
return transmute(u16)u16be(value)
|
||||
}
|
||||
|
||||
HOST_TO_NET_32 :: #force_inline proc(value: u32) -> u32 {
|
||||
HOST_TO_NET_32 :: #force_inline proc "contextless" (value: u32) -> u32 {
|
||||
return transmute(u32)u32be(value)
|
||||
}
|
||||
|
||||
NET_TO_HOST_16 :: #force_inline proc(value: u16) -> u16 {
|
||||
NET_TO_HOST_16 :: #force_inline proc "contextless" (value: u16) -> u16 {
|
||||
return u16(transmute(u16be)value)
|
||||
}
|
||||
|
||||
NET_TO_HOST_32 :: #force_inline proc(value: u32) -> u32 {
|
||||
NET_TO_HOST_32 :: #force_inline proc "contextless" (value: u32) -> u32 {
|
||||
return u32(transmute(u32be)value)
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ PacketFreeCallback :: proc "c" (packet: ^Packet)
|
||||
Packet :: struct {
|
||||
referenceCount: uint,
|
||||
flags: u32,
|
||||
data: [^]u8,
|
||||
data: [^]u8 `fmt:"v,dataLength"`,
|
||||
dataLength: uint,
|
||||
freeCallback: PacketFreeCallback,
|
||||
userData: rawptr,
|
||||
@@ -148,7 +148,7 @@ IncomingCommand :: struct {
|
||||
command: Protocol,
|
||||
fragmentCount: u32,
|
||||
fragmentsRemaining: u32,
|
||||
fragments: [^]u32,
|
||||
fragments: [^]u32 `fmt:"v,fragmentCount"`,
|
||||
packet: ^Packet,
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ Peer :: struct {
|
||||
address: Address,
|
||||
data: rawptr,
|
||||
state: PeerState,
|
||||
channels: [^]Channel,
|
||||
channels: [^]Channel `fmt:"v,channelCount"`,
|
||||
channelCount: uint,
|
||||
incomingBandwidth: u32,
|
||||
outgoingBandwidth: u32,
|
||||
@@ -292,7 +292,7 @@ Host :: struct {
|
||||
mtu: u32,
|
||||
randomSeed: u32,
|
||||
recalculateBandwidthLimits: i32,
|
||||
peers: [^]Peer,
|
||||
peers: [^]Peer `fmt:"v,peerCount"`,
|
||||
peerCount: uint,
|
||||
channelLimit: uint,
|
||||
serviceTime: u32,
|
||||
@@ -308,7 +308,7 @@ Host :: struct {
|
||||
compressor: Compressor,
|
||||
packetData: [2][PROTOCOL_MAXIMUM_MTU]u8,
|
||||
receivedAddress: Address,
|
||||
receivedData: [^]u8,
|
||||
receivedData: [^]u8 `fmt:"v,receivedDataLength"`,
|
||||
receivedDataLength: uint,
|
||||
totalSentData: u32,
|
||||
totalSentPackets: u32,
|
||||
|
||||
Vendored
+5
-5
@@ -2,22 +2,22 @@ package ENet
|
||||
|
||||
TIME_OVERFLOW :: u32(86400000)
|
||||
|
||||
TIME_LESS :: #force_inline proc(a, b: u32) -> bool {
|
||||
TIME_LESS :: #force_inline proc "contextless" (a, b: u32) -> bool {
|
||||
return a - b >= TIME_OVERFLOW
|
||||
}
|
||||
|
||||
TIME_GREATER :: #force_inline proc(a, b: u32) -> bool {
|
||||
TIME_GREATER :: #force_inline proc "contextless" (a, b: u32) -> bool {
|
||||
return b - a >= TIME_OVERFLOW
|
||||
}
|
||||
|
||||
TIME_LESS_EQUAL :: #force_inline proc(a, b: u32) -> bool {
|
||||
TIME_LESS_EQUAL :: #force_inline proc "contextless" (a, b: u32) -> bool {
|
||||
return !TIME_GREATER(a, b)
|
||||
}
|
||||
|
||||
TIME_GREATER_EQUAL :: #force_inline proc(a, b: u32) -> bool {
|
||||
TIME_GREATER_EQUAL :: #force_inline proc "contextless" (a, b: u32) -> bool {
|
||||
return TIME_LESS(a, b)
|
||||
}
|
||||
|
||||
TIME_DIFFERENCE :: #force_inline proc(a, b: u32) -> u32 {
|
||||
TIME_DIFFERENCE :: #force_inline proc "contextless" (a, b: u32) -> u32 {
|
||||
return a - b >= TIME_OVERFLOW ? b - a : a - b
|
||||
}
|
||||
Vendored
+8
-8
@@ -12,21 +12,21 @@ import "core:c"
|
||||
fds_bits: [FD_SETSIZE / 8 / size_of(c.long)]c.ulong,
|
||||
}
|
||||
|
||||
@(private="file") FD_ZERO :: #force_inline proc(s: ^fd_set) {
|
||||
@(private="file") FD_ZERO :: #force_inline proc "contextless" (s: ^fd_set) {
|
||||
for i := size_of(fd_set) / size_of(c.long); i != 0; i -= 1 {
|
||||
s.fds_bits[i] = 0
|
||||
}
|
||||
}
|
||||
|
||||
@(private="file") FD_SET :: #force_inline proc(d: i32, s: ^fd_set) {
|
||||
@(private="file") FD_SET :: #force_inline proc "contextless" (d: i32, s: ^fd_set) {
|
||||
s.fds_bits[d / (8 * size_of(c.long))] |= c.ulong(1) << (c.ulong(d) % (8 * size_of(c.ulong)))
|
||||
}
|
||||
|
||||
@(private="file") FD_CLR :: #force_inline proc(d: i32, s: ^fd_set) {
|
||||
@(private="file") FD_CLR :: #force_inline proc "contextless" (d: i32, s: ^fd_set) {
|
||||
s.fds_bits[d / (8 * size_of(c.long))] &~= c.ulong(1) << (c.ulong(d) % (8 * size_of(c.ulong)))
|
||||
}
|
||||
|
||||
@(private="file") FD_ISSET :: #force_inline proc(d: i32, s: ^fd_set) -> bool {
|
||||
@(private="file") FD_ISSET :: #force_inline proc "contextless" (d: i32, s: ^fd_set) -> bool {
|
||||
return (s.fds_bits[d / (8 * size_of(c.long))] & c.ulong(1) << (c.ulong(d) % (8 * size_of(c.ulong)))) != 0
|
||||
}
|
||||
// }
|
||||
@@ -42,18 +42,18 @@ Buffer :: struct {
|
||||
|
||||
SocketSet :: distinct fd_set
|
||||
|
||||
SOCKETSET_EMPTY :: #force_inline proc(sockset: ^SocketSet) {
|
||||
SOCKETSET_EMPTY :: #force_inline proc "contextless" (sockset: ^SocketSet) {
|
||||
FD_ZERO(cast(^fd_set)sockset)
|
||||
}
|
||||
|
||||
SOCKETSET_ADD :: #force_inline proc(sockset: ^SocketSet, socket: Socket) {
|
||||
SOCKETSET_ADD :: #force_inline proc "contextless" (sockset: ^SocketSet, socket: Socket) {
|
||||
FD_SET(i32(socket), cast(^fd_set)sockset)
|
||||
}
|
||||
|
||||
SOCKETSET_REMOVE :: #force_inline proc(sockset: ^SocketSet, socket: Socket) {
|
||||
SOCKETSET_REMOVE :: #force_inline proc "contextless" (sockset: ^SocketSet, socket: Socket) {
|
||||
FD_CLR(i32(socket), cast(^fd_set)sockset)
|
||||
}
|
||||
|
||||
SOCKSET_CHECK :: #force_inline proc(sockset: ^SocketSet, socket: Socket) -> bool {
|
||||
SOCKSET_CHECK :: #force_inline proc "contextless" (sockset: ^SocketSet, socket: Socket) -> bool {
|
||||
return FD_ISSET(i32(socket), cast(^fd_set)sockset)
|
||||
}
|
||||
|
||||
Vendored
+8
-8
@@ -20,7 +20,7 @@ foreign WinSock2 {
|
||||
fd_array: [FD_SETSIZE]SOCKET,
|
||||
}
|
||||
|
||||
@(private="file") FD_CLR :: proc(fd: SOCKET, s: ^fd_set) {
|
||||
@(private="file") FD_CLR :: proc "contextless" (fd: SOCKET, s: ^fd_set) {
|
||||
for i := u32(0); i < s.fd_count; i += 1 {
|
||||
if s.fd_array[i] == fd {
|
||||
for i < s.fd_count - 1 {
|
||||
@@ -33,7 +33,7 @@ foreign WinSock2 {
|
||||
}
|
||||
}
|
||||
|
||||
@(private="file") FD_SET :: proc(fd: SOCKET, s: ^fd_set) {
|
||||
@(private="file") FD_SET :: proc "contextless" (fd: SOCKET, s: ^fd_set) {
|
||||
for i := u32(0); i < s.fd_count; i += 1 {
|
||||
if s.fd_array[i] == fd {
|
||||
return
|
||||
@@ -46,11 +46,11 @@ foreign WinSock2 {
|
||||
s.fd_count += 1
|
||||
}
|
||||
|
||||
@(private="file") FD_ZERO :: #force_inline proc (s: ^fd_set) {
|
||||
@(private="file") FD_ZERO :: #force_inline proc "contextless" (s: ^fd_set) {
|
||||
s.fd_count = 0
|
||||
}
|
||||
|
||||
@(private="file") FD_ISSET :: #force_inline proc (fd: SOCKET, s: ^fd_set) -> bool {
|
||||
@(private="file") FD_ISSET :: #force_inline proc "contextless" (fd: SOCKET, s: ^fd_set) -> bool {
|
||||
return __WSAFDIsSet(fd, s) != 0
|
||||
}
|
||||
// }
|
||||
@@ -66,18 +66,18 @@ Buffer :: struct {
|
||||
|
||||
SocketSet :: distinct fd_set
|
||||
|
||||
SOCKETSET_EMPTY :: #force_inline proc(sockset: ^SocketSet) {
|
||||
SOCKETSET_EMPTY :: #force_inline proc "contextless" (sockset: ^SocketSet) {
|
||||
FD_ZERO(cast(^fd_set)sockset)
|
||||
}
|
||||
|
||||
SOCKETSET_ADD :: #force_inline proc(sockset: ^SocketSet, socket: Socket) {
|
||||
SOCKETSET_ADD :: #force_inline proc "contextless" (sockset: ^SocketSet, socket: Socket) {
|
||||
FD_SET(SOCKET(socket), cast(^fd_set)sockset)
|
||||
}
|
||||
|
||||
SOCKETSET_REMOVE :: #force_inline proc(sockset: ^SocketSet, socket: Socket) {
|
||||
SOCKETSET_REMOVE :: #force_inline proc "contextless" (sockset: ^SocketSet, socket: Socket) {
|
||||
FD_CLR(SOCKET(socket), cast(^fd_set)sockset)
|
||||
}
|
||||
|
||||
SOCKSET_CHECK :: #force_inline proc(sockset: ^SocketSet, socket: Socket) -> bool {
|
||||
SOCKSET_CHECK :: #force_inline proc "contextless" (sockset: ^SocketSet, socket: Socket) -> bool {
|
||||
return FD_ISSET(SOCKET(socket), cast(^fd_set)sockset)
|
||||
}
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Erin Catto
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
Vendored
+32
@@ -0,0 +1,32 @@
|
||||

|
||||
|
||||
# Status
|
||||
[](https://github.com/erincatto/box2c/actions)
|
||||
|
||||
# Box2D v3.0 Notes
|
||||
This repository is beta and ready for testing. It should build on recent versions of clang and gcc. However, you will need the latest Visual Studio version for C11 atomics to compile (17.8.3+).
|
||||
|
||||
AVX2 CPU support is assumed. You can turn this off in the CMake options and use SSE2 instead.
|
||||
|
||||
# Box2D
|
||||
Box2D is a 2D physics engine for games.
|
||||
|
||||
## Contributing
|
||||
Please do not submit pull requests with new features or core library changes. Instead, please file an issue first for discussion. For bugs, I prefer detailed bug reports over pull requests.
|
||||
|
||||
# Giving Feedback
|
||||
Please visit the discussions tab, file an issue, or start a chat on discord.
|
||||
|
||||
## Community
|
||||
- [Discord](https://discord.gg/NKYgCBP)
|
||||
|
||||
## License
|
||||
Box2D is developed by Erin Catto, and uses the [MIT license](https://en.wikipedia.org/wiki/MIT_License).
|
||||
|
||||
## Sponsorship
|
||||
Support development of Box2D through [Github Sponsors](https://github.com/sponsors/erincatto)
|
||||
|
||||
## Ports, wrappers, and Bindings
|
||||
- https://github.com/odin-lang/Odin/tree/master/vendor/box2d
|
||||
- https://github.com/EnokViking/Box2DBeef
|
||||
- https://github.com/HolyBlackCat/box2cpp
|
||||
Vendored
+1523
File diff suppressed because it is too large
Load Diff
+72
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eu
|
||||
|
||||
VERSION="3.0.0"
|
||||
RELEASE="https://github.com/erincatto/box2d/archive/refs/tags/v$VERSION.tar.gz"
|
||||
|
||||
cd "$(odin root)"/vendor/box2d
|
||||
|
||||
curl -O -L "$RELEASE"
|
||||
tar -xzvf "v$VERSION.tar.gz"
|
||||
|
||||
cd "box2d-$VERSION"
|
||||
|
||||
DISABLE_FLAGS="-DBOX2D_SAMPLES=OFF -DBOX2D_VALIDATE=OFF -DBOX2D_UNIT_TESTS=OFF"
|
||||
|
||||
case "$(uname -s)" in
|
||||
Darwin)
|
||||
export MACOSX_DEPLOYMENT_TARGET="11"
|
||||
|
||||
case "$(uname -m)" in
|
||||
"x86_64" | "amd64")
|
||||
rm -rf build
|
||||
mkdir build
|
||||
cmake $DISABLE_FLAGS -DBOX2D_AVX2=ON -DCMAKE_OSX_ARCHITECTURES=x86_64 -S . -B build
|
||||
cmake --build build
|
||||
cp build/src/libbox2d.a ../lib/box2d_darwin_amd64_avx2.a
|
||||
|
||||
rm -rf build
|
||||
mkdir build
|
||||
cmake $DISABLE_FLAGS -DBOX2D_AVX2=OFF -DCMAKE_OSX_ARCHITECTURES=x86_64 -S . -B build
|
||||
cmake --build build
|
||||
cp build/src/libbox2d.a ../lib/box2d_darwin_amd64_sse2.a
|
||||
;;
|
||||
*)
|
||||
rm -rf build
|
||||
mkdir build
|
||||
cmake $DISABLE_FLAGS -DCMAKE_OSX_ARCHITECTURES=arm64 -S . -B build
|
||||
cmake --build build
|
||||
cp build/src/libbox2d.a ../lib/box2d_darwin_arm64.a
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
case "$(uname -m)" in
|
||||
"x86_64" | "amd64")
|
||||
rm -rf build
|
||||
mkdir build
|
||||
cmake $DISABLE_FLAGS -DBOX2D_AVX2=ON -S . -B build
|
||||
cmake --build build
|
||||
cp build/src/libbox2d.a ../lib/box2d_other_amd64_avx2.a
|
||||
|
||||
rm -rf build
|
||||
mkdir build
|
||||
cmake $DISABLE_FLAGS -DBOX2D_AVX2=OFF -S . -B build
|
||||
cmake --build build
|
||||
cp build/src/libbox2d.a ../lib/box2d_other_amd64_sse2.a
|
||||
;;
|
||||
*)
|
||||
rm -rf build
|
||||
mkdir build
|
||||
cmake $DISABLE_FLAGS -DCMAKE_OSX_ARCHITECTURES=arm64 -S . -B build
|
||||
cmake --build build
|
||||
cp build/src/libbox2d.a ../lib/box2d_other.a
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
cd ..
|
||||
|
||||
rm -rf v3.0.0.tar.gz
|
||||
rm -rf box2d-3.0.0
|
||||
Vendored
+473
@@ -0,0 +1,473 @@
|
||||
package vendor_box2d
|
||||
|
||||
import "core:c"
|
||||
|
||||
|
||||
// The maximum number of vertices on a convex polygon. Changing this affects performance even if you
|
||||
// don't use more vertices.
|
||||
maxPolygonVertices :: 8
|
||||
|
||||
// Low level ray-cast input data
|
||||
RayCastInput :: struct {
|
||||
// Start point of the ray cast
|
||||
origin: Vec2,
|
||||
|
||||
// Translation of the ray cast
|
||||
translation: Vec2,
|
||||
|
||||
// The maximum fraction of the translation to consider, typically 1
|
||||
maxFraction: f32,
|
||||
}
|
||||
|
||||
// Low level shape cast input in generic form. This allows casting an arbitrary point
|
||||
// cloud wrap with a radius. For example, a circle is a single point with a non-zero radius.
|
||||
// A capsule is two points with a non-zero radius. A box is four points with a zero radius.
|
||||
ShapeCastInput :: struct {
|
||||
// A point cloud to cast
|
||||
points: [maxPolygonVertices]Vec2 `fmt:"v,count"`,
|
||||
|
||||
// The number of points
|
||||
count: i32,
|
||||
|
||||
// The radius around the point cloud
|
||||
radius: f32,
|
||||
|
||||
// The translation of the shape cast
|
||||
translation: Vec2,
|
||||
|
||||
// The maximum fraction of the translation to consider, typically 1
|
||||
maxFraction: f32,
|
||||
}
|
||||
|
||||
// Low level ray-cast or shape-cast output data
|
||||
CastOutput :: struct {
|
||||
// The surface normal at the hit point
|
||||
normal: Vec2,
|
||||
|
||||
// The surface hit point
|
||||
point: Vec2,
|
||||
|
||||
// The fraction of the input translation at collision
|
||||
fraction: f32,
|
||||
|
||||
// The number of iterations used
|
||||
iterations: i32,
|
||||
|
||||
// Did the cast hit?
|
||||
hit: bool,
|
||||
}
|
||||
|
||||
// This holds the mass data computed for a shape.
|
||||
MassData :: struct {
|
||||
// The mass of the shape, usually in kilograms.
|
||||
mass: f32,
|
||||
|
||||
// The position of the shape's centroid relative to the shape's origin.
|
||||
center: Vec2,
|
||||
|
||||
// The rotational inertia of the shape about the local origin.
|
||||
rotationalInertia: f32,
|
||||
}
|
||||
|
||||
// A solid circle
|
||||
Circle :: struct {
|
||||
// The local center
|
||||
center: Vec2,
|
||||
|
||||
// The radius
|
||||
radius: f32,
|
||||
}
|
||||
|
||||
// A solid capsule can be viewed as two semicircles connected
|
||||
// by a rectangle.
|
||||
Capsule :: struct {
|
||||
// Local center of the first semicircle
|
||||
center1: Vec2,
|
||||
|
||||
// Local center of the second semicircle
|
||||
center2: Vec2,
|
||||
|
||||
// The radius of the semicircles
|
||||
radius: f32,
|
||||
}
|
||||
|
||||
// A solid convex polygon. It is assumed that the interior of the polygon is to
|
||||
// the left of each edge.
|
||||
// Polygons have a maximum number of vertices equal to maxPolygonVertices.
|
||||
// In most cases you should not need many vertices for a convex polygon.
|
||||
// @warning DO NOT fill this out manually, instead use a helper function like
|
||||
// b2MakePolygon or b2MakeBox.
|
||||
Polygon :: struct {
|
||||
// The polygon vertices
|
||||
vertices: [maxPolygonVertices]Vec2 `fmt:"v,count"`,
|
||||
|
||||
// The outward normal vectors of the polygon sides
|
||||
normals: [maxPolygonVertices]Vec2 `fmt:"v,count"`,
|
||||
|
||||
// The centroid of the polygon
|
||||
centroid: Vec2,
|
||||
|
||||
// The external radius for rounded polygons
|
||||
radius: f32,
|
||||
|
||||
// The number of polygon vertices
|
||||
count: i32,
|
||||
}
|
||||
|
||||
// A line segment with two-sided collision.
|
||||
Segment :: struct {
|
||||
// The first point
|
||||
point1: Vec2,
|
||||
|
||||
// The second point
|
||||
point2: Vec2,
|
||||
}
|
||||
|
||||
// A smooth line segment with one-sided collision. Only collides on the right side.
|
||||
// Several of these are generated for a chain shape.
|
||||
// ghost1 -> point1 -> point2 -> ghost2
|
||||
SmoothSegment :: struct {
|
||||
// The tail ghost vertex
|
||||
ghost1: Vec2,
|
||||
|
||||
// The line segment
|
||||
segment: Segment,
|
||||
|
||||
// The head ghost vertex
|
||||
ghost2: Vec2,
|
||||
|
||||
// The owning chain shape index (internal usage only)
|
||||
chainId: i32,
|
||||
}
|
||||
|
||||
|
||||
// A convex hull. Used to create convex polygons.
|
||||
// @warning Do not modify these values directly, instead use b2ComputeHull()
|
||||
Hull :: struct {
|
||||
// The final points of the hull
|
||||
points: [maxPolygonVertices]Vec2 `fmt:"v,count"`,
|
||||
|
||||
// The number of points
|
||||
count: i32,
|
||||
}
|
||||
|
||||
/**
|
||||
* @defgroup distance Distance
|
||||
* Functions for computing the distance between shapes.
|
||||
*
|
||||
* These are advanced functions you can use to perform distance calculations. There
|
||||
* are functions for computing the closest points between shapes, doing linear shape casts,
|
||||
* and doing rotational shape casts. The latter is called time of impact (TOI).
|
||||
*/
|
||||
|
||||
// Result of computing the distance between two line segments
|
||||
SegmentDistanceResult :: struct {
|
||||
// The closest point on the first segment
|
||||
closest1: Vec2,
|
||||
|
||||
// The closest point on the second segment
|
||||
closest2: Vec2,
|
||||
|
||||
// The barycentric coordinate on the first segment
|
||||
fraction1: f32,
|
||||
|
||||
// The barycentric coordinate on the second segment
|
||||
fraction2: f32,
|
||||
|
||||
// The squared distance between the closest points
|
||||
distanceSquared: f32,
|
||||
}
|
||||
|
||||
// A distance proxy is used by the GJK algorithm. It encapsulates any shape.
|
||||
DistanceProxy :: struct {
|
||||
// The point cloud
|
||||
points: [maxPolygonVertices]Vec2 `fmt:"v,count"`,
|
||||
|
||||
// The number of points
|
||||
count: i32,
|
||||
|
||||
// The external radius of the point cloud
|
||||
radius: f32,
|
||||
}
|
||||
|
||||
// Used to warm start b2Distance. Set count to zero on first call or
|
||||
// use zero initialization.
|
||||
DistanceCache :: struct {
|
||||
// The number of stored simplex points
|
||||
count: u16,
|
||||
|
||||
// The cached simplex indices on shape A
|
||||
indexA: [3]u8 `fmt:"v,count"`,
|
||||
|
||||
// The cached simplex indices on shape B
|
||||
indexB: [3]u8 `fmt:"v,count"`,
|
||||
}
|
||||
|
||||
emptyDistanceCache :: DistanceCache{}
|
||||
|
||||
// Input for b2ShapeDistance
|
||||
DistanceInput :: struct {
|
||||
// The proxy for shape A
|
||||
proxyA: DistanceProxy,
|
||||
|
||||
// The proxy for shape B
|
||||
proxyB: DistanceProxy,
|
||||
|
||||
// The world transform for shape A
|
||||
transformA: Transform,
|
||||
|
||||
// The world transform for shape B
|
||||
transformB: Transform,
|
||||
|
||||
// Should the proxy radius be considered?
|
||||
useRadii: bool,
|
||||
}
|
||||
|
||||
// Output for b2ShapeDistance
|
||||
DistanceOutput :: struct {
|
||||
pointA: Vec2, // Closest point on shapeA
|
||||
pointB: Vec2, // Closest point on shapeB
|
||||
distance: f32, // The final distance, zero if overlapped
|
||||
iterations: i32, // Number of GJK iterations used
|
||||
simplexCount: i32, // The number of simplexes stored in the simplex array
|
||||
}
|
||||
|
||||
// Simplex vertex for debugging the GJK algorithm
|
||||
SimplexVertex :: struct {
|
||||
wA: Vec2, // support point in proxyA
|
||||
wB: Vec2, // support point in proxyB
|
||||
w: Vec2, // wB - wA
|
||||
a: f32, // barycentric coordinate for closest point
|
||||
indexA: i32, // wA index
|
||||
indexB: i32, // wB index
|
||||
}
|
||||
|
||||
// Simplex from the GJK algorithm
|
||||
Simplex :: struct {
|
||||
v1, v2, v3: SimplexVertex `fmt:"v,count"`, // vertices
|
||||
count: i32, // number of valid vertices
|
||||
}
|
||||
|
||||
// Input parameters for b2ShapeCast
|
||||
ShapeCastPairInput :: struct {
|
||||
proxyA: DistanceProxy, // The proxy for shape A
|
||||
proxyB: DistanceProxy, // The proxy for shape B
|
||||
transformA: Transform, // The world transform for shape A
|
||||
transformB: Transform, // The world transform for shape B
|
||||
translationB: Vec2, // The translation of shape B
|
||||
maxFraction: f32, // The fraction of the translation to consider, typically 1
|
||||
}
|
||||
|
||||
|
||||
// This describes the motion of a body/shape for TOI computation. Shapes are defined with respect to the body origin,
|
||||
// which may not coincide with the center of mass. However, to support dynamics we must interpolate the center of mass
|
||||
// position.
|
||||
Sweep :: struct {
|
||||
localCenter: Vec2, // Local center of mass position
|
||||
c1: Vec2, // Starting center of mass world position
|
||||
c2: Vec2, // Ending center of mass world position
|
||||
q1: Rot, // Starting world rotation
|
||||
q2: Rot, // Ending world rotation
|
||||
}
|
||||
|
||||
// Input parameters for b2TimeOfImpact
|
||||
TOIInput :: struct {
|
||||
proxyA: DistanceProxy, // The proxy for shape A
|
||||
proxyB: DistanceProxy, // The proxy for shape B
|
||||
sweepA: Sweep, // The movement of shape A
|
||||
sweepB: Sweep, // The movement of shape B
|
||||
tMax: f32, // Defines the sweep interval [0, tMax]
|
||||
}
|
||||
|
||||
// Describes the TOI output
|
||||
TOIState :: enum c.int {
|
||||
Unknown,
|
||||
Failed,
|
||||
Overlapped,
|
||||
Hit,
|
||||
Separated,
|
||||
}
|
||||
|
||||
// Output parameters for b2TimeOfImpact.
|
||||
TOIOutput :: struct {
|
||||
state: TOIState, // The type of result
|
||||
t: f32, // The time of the collision
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup collision Collision
|
||||
* @brief Functions for colliding pairs of shapes
|
||||
*/
|
||||
|
||||
// A manifold point is a contact point belonging to a contact
|
||||
// manifold. It holds details related to the geometry and dynamics
|
||||
// of the contact points.
|
||||
ManifoldPoint :: struct {
|
||||
// Location of the contact point in world space. Subject to precision loss at large coordinates.
|
||||
// @note Should only be used for debugging.
|
||||
point: Vec2,
|
||||
|
||||
// Location of the contact point relative to bodyA's origin in world space
|
||||
// @note When used internally to the Box2D solver, these are relative to the center of mass.
|
||||
anchorA: Vec2,
|
||||
|
||||
// Location of the contact point relative to bodyB's origin in world space
|
||||
anchorB: Vec2,
|
||||
|
||||
// The separation of the contact point, negative if penetrating
|
||||
separation: f32,
|
||||
|
||||
// The impulse along the manifold normal vector.
|
||||
normalImpulse: f32,
|
||||
|
||||
// The friction impulse
|
||||
tangentImpulse: f32,
|
||||
|
||||
// The maximum normal impulse applied during sub-stepping
|
||||
// todo not sure this is needed
|
||||
maxNormalImpulse: f32,
|
||||
|
||||
// Relative normal velocity pre-solve. Used for hit events. If the normal impulse is
|
||||
// zero then there was no hit. Negative means shapes are approaching.
|
||||
normalVelocity: f32,
|
||||
|
||||
// Uniquely identifies a contact point between two shapes
|
||||
id: u16,
|
||||
|
||||
// Did this contact point exist the previous step?
|
||||
persisted: bool,
|
||||
}
|
||||
|
||||
// A contact manifold describes the contact points between colliding shapes
|
||||
Manifold :: struct {
|
||||
// The manifold points, up to two are possible in 2D
|
||||
points: [2]ManifoldPoint,
|
||||
|
||||
// The unit normal vector in world space, points from shape A to bodyB
|
||||
normal: Vec2,
|
||||
|
||||
// The number of contacts points, will be 0, 1, or 2
|
||||
pointCount: i32,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup tree Dynamic Tree
|
||||
* The dynamic tree is a binary AABB tree to organize and query large numbers of geometric objects
|
||||
*
|
||||
* Box2D uses the dynamic tree internally to sort collision shapes into a binary bounding volume hierarchy.
|
||||
* This data structure may have uses in games for organizing other geometry data and may be used independently
|
||||
* of Box2D rigid body simulation.
|
||||
*
|
||||
* A dynamic AABB tree broad-phase, inspired by Nathanael Presson's btDbvt.
|
||||
* A dynamic tree arranges data in a binary tree to accelerate
|
||||
* queries such as AABB queries and ray casts. Leaf nodes are proxies
|
||||
* with an AABB. These are used to hold a user collision object, such as a reference to a b2Shape.
|
||||
* Nodes are pooled and relocatable, so I use node indices rather than pointers.
|
||||
* The dynamic tree is made available for advanced users that would like to use it to organize
|
||||
* spatial game data besides rigid bodies.
|
||||
*
|
||||
* @note This is an advanced feature and normally not used by applications directly.
|
||||
*/
|
||||
|
||||
// The default category bit for a tree proxy. Used for collision filtering.
|
||||
defaultCategoryBits :: 0x00000001
|
||||
|
||||
// Convenience mask bits to use when you don't need collision filtering and just want
|
||||
// all results.
|
||||
defaultMaskBits :: 0xFFFFFFFF
|
||||
|
||||
// A node in the dynamic tree. This is private data placed here for performance reasons.
|
||||
// 16 + 16 + 8 + pad(8)
|
||||
TreeNode :: struct {
|
||||
// The node bounding box
|
||||
aabb: AABB, // 16
|
||||
|
||||
// Category bits for collision filtering
|
||||
categoryBits: u32, // 4
|
||||
|
||||
using _: struct #raw_union {
|
||||
// The node parent index
|
||||
parent: i32,
|
||||
|
||||
// The node freelist next index
|
||||
next: i32,
|
||||
}, // 4
|
||||
|
||||
// Child 1 index
|
||||
child1: i32, // 4
|
||||
|
||||
// Child 2 index
|
||||
child2: i32, // 4
|
||||
|
||||
// User data
|
||||
// todo could be union with child index
|
||||
userData: i32, // 4
|
||||
|
||||
// Leaf = 0, free node = -1
|
||||
height: i16, // 2
|
||||
|
||||
// Has the AABB been enlarged?
|
||||
enlarged: bool, // 1
|
||||
|
||||
// Padding for clarity
|
||||
_: [9]byte,
|
||||
}
|
||||
|
||||
// The dynamic tree structure. This should be considered private data.
|
||||
// It is placed here for performance reasons.
|
||||
DynamicTree :: struct {
|
||||
// The tree nodes
|
||||
nodes: [^]TreeNode `fmt"v,nodeCount"`,
|
||||
|
||||
// The root index
|
||||
root: i32,
|
||||
|
||||
// The number of nodes
|
||||
nodeCount: i32,
|
||||
|
||||
// The allocated node space
|
||||
nodeCapacity: i32,
|
||||
|
||||
// Node free list
|
||||
freeList: i32,
|
||||
|
||||
// Number of proxies created
|
||||
proxyCount: i32,
|
||||
|
||||
// Leaf indices for rebuild
|
||||
leafIndices: [^]i32,
|
||||
|
||||
// Leaf bounding boxes for rebuild
|
||||
leafBoxes: [^]AABB,
|
||||
|
||||
// Leaf bounding box centers for rebuild
|
||||
leafCenters: [^]Vec2,
|
||||
|
||||
// Bins for sorting during rebuild
|
||||
binIndices: [^]i32,
|
||||
|
||||
// Allocated space for rebuilding
|
||||
rebuildCapacity: i32,
|
||||
}
|
||||
|
||||
// This function receives proxies found in the AABB query.
|
||||
// @return true if the query should continue
|
||||
TreeQueryCallbackFcn :: #type proc "c" (proxyId: i32, userData: i32, ctx: rawptr) -> bool
|
||||
|
||||
// This function receives clipped ray-cast input for a proxy. The function
|
||||
// returns the new ray fraction.
|
||||
// - return a value of 0 to terminate the ray-cast
|
||||
// - return a value less than input->maxFraction to clip the ray
|
||||
// - return a value of input->maxFraction to continue the ray cast without clipping
|
||||
TreeShapeCastCallbackFcn :: #type proc "c" (#by_ptr input: ShapeCastInput, proxyId: i32, userData: i32, ctx: rawptr) -> f32
|
||||
|
||||
|
||||
// This function receives clipped raycast input for a proxy. The function
|
||||
// returns the new ray fraction.
|
||||
// - return a value of 0 to terminate the ray cast
|
||||
// - return a value less than input->maxFraction to clip the ray
|
||||
// - return a value of input->maxFraction to continue the ray cast without clipping
|
||||
TreeRayCastCallbackFcn :: #type proc "c" (#by_ptr input: RayCastInput, proxyId: i32, userData: i32, ctx: rawptr) -> f32
|
||||
Vendored
+87
@@ -0,0 +1,87 @@
|
||||
package vendor_box2d
|
||||
|
||||
import "base:intrinsics"
|
||||
|
||||
/**
|
||||
* @defgroup id Ids
|
||||
* These ids serve as handles to internal Box2D objects.
|
||||
* These should be considered opaque data and passed by value.
|
||||
* Include this header if you need the id types and not the whole Box2D API.
|
||||
* All ids are considered null if initialized to zero.
|
||||
*
|
||||
* For example in Odin:
|
||||
*
|
||||
* @code{.odin}
|
||||
* worldId := b2.WorldId{}
|
||||
* @endcode
|
||||
*
|
||||
* This is considered null.
|
||||
*
|
||||
* @warning Do not use the internals of these ids. They are subject to change. Ids should be treated as opaque objects.
|
||||
* @warning You should use ids to access objects in Box2D. Do not access files within the src folder. Such usage is unsupported.
|
||||
*/
|
||||
|
||||
/// World id references a world instance. This should be treated as an opaque handle.
|
||||
WorldId :: struct {
|
||||
index1: u16,
|
||||
revision: u16,
|
||||
}
|
||||
|
||||
/// Body id references a body instance. This should be treated as an opaque handle.
|
||||
BodyId :: struct {
|
||||
index1: i32,
|
||||
world0: u16,
|
||||
revision: u16,
|
||||
}
|
||||
|
||||
/// Shape id references a shape instance. This should be treated as an opaque handle.
|
||||
ShapeId :: struct {
|
||||
index1: i32,
|
||||
world0: u16,
|
||||
revision: u16,
|
||||
}
|
||||
|
||||
/// Joint id references a joint instance. This should be treated as an opaque handle.
|
||||
JointId :: struct {
|
||||
index1: i32,
|
||||
world0: u16,
|
||||
revision: u16,
|
||||
}
|
||||
|
||||
/// Chain id references a chain instances. This should be treated as an opaque handle.
|
||||
ChainId :: struct {
|
||||
index1: i32,
|
||||
world0: u16,
|
||||
revision: u16,
|
||||
}
|
||||
|
||||
/// Use these to make your identifiers null.
|
||||
/// You may also use zero initialization to get null.
|
||||
nullWorldId :: WorldId{}
|
||||
nullBodyId :: BodyId{}
|
||||
nullShapeId :: ShapeId{}
|
||||
nullJointId :: JointId{}
|
||||
nullChainId :: ChainId{}
|
||||
|
||||
/// Macro to determine if any id is null.
|
||||
IS_NULL :: #force_inline proc "c" (id: $T) -> bool
|
||||
where intrinsics.type_is_struct(T),
|
||||
intrinsics.type_has_field(T, "index1") {
|
||||
return id.index1 == 0
|
||||
}
|
||||
|
||||
/// Macro to determine if any id is non-null.
|
||||
IS_NON_NULL :: #force_inline proc "c" (id: $T) -> bool
|
||||
where intrinsics.type_is_struct(T),
|
||||
intrinsics.type_has_field(T, "index1") {
|
||||
return id.index1 != 0
|
||||
}
|
||||
|
||||
/// Compare two ids for equality. Doesn't work for b2WorldId.
|
||||
ID_EQUALS :: #force_inline proc "c" (id1, id2: $T) -> bool
|
||||
where intrinsics.type_is_struct(T),
|
||||
intrinsics.type_has_field(T, "index1"),
|
||||
intrinsics.type_has_field(T, "world0"),
|
||||
intrinsics.type_has_field(T, "revision") {
|
||||
return id1.index1 == id2.index1 && id1.world0 == id2.world0 && id1.revision == id2.revision
|
||||
}
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Vendored
+522
@@ -0,0 +1,522 @@
|
||||
package vendor_box2d
|
||||
|
||||
import "core:c"
|
||||
import "core:math"
|
||||
|
||||
pi :: 3.14159265359
|
||||
|
||||
Vec2 :: [2]f32
|
||||
Rot :: struct {
|
||||
c, s: f32, // cosine and sine
|
||||
}
|
||||
|
||||
Transform :: struct {
|
||||
p: Vec2,
|
||||
q: Rot,
|
||||
}
|
||||
|
||||
Mat22 :: matrix[2, 2]f32
|
||||
AABB :: struct {
|
||||
lowerBound: Vec2,
|
||||
upperBound: Vec2,
|
||||
}
|
||||
|
||||
Vec2_zero :: Vec2{0, 0}
|
||||
Rot_identity :: Rot{1, 0}
|
||||
Transform_identity :: Transform{{0, 0}, {1, 0}}
|
||||
Mat22_zero :: Mat22{0, 0, 0, 0}
|
||||
|
||||
|
||||
// @return the minimum of two floats
|
||||
@(deprecated="Prefer the built-in 'min(a, b)'", require_results)
|
||||
MinFloat :: proc "c" (a, b: f32) -> f32 {
|
||||
return min(a, b)
|
||||
}
|
||||
|
||||
// @return the maximum of two floats
|
||||
@(deprecated="Prefer the built-in 'max(a, b)'", require_results)
|
||||
MaxFloat :: proc "c" (a, b: f32) -> f32 {
|
||||
return max(a, b)
|
||||
}
|
||||
|
||||
// @return the absolute value of a float
|
||||
@(deprecated="Prefer the built-in 'abs(a)'", require_results)
|
||||
AbsFloat :: proc "c" (a: f32) -> f32 {
|
||||
return abs(a)
|
||||
}
|
||||
|
||||
// @return a f32 clamped between a lower and upper bound
|
||||
@(deprecated="Prefer the built-in 'clamp(a, lower, upper)'", require_results)
|
||||
ClampFloat :: proc "c" (a, lower, upper: f32) -> f32 {
|
||||
return clamp(a, lower, upper)
|
||||
}
|
||||
|
||||
// @return the minimum of two integers
|
||||
@(deprecated="Prefer the built-in 'min(a, b)'", require_results)
|
||||
MinInt :: proc "c" (a, b: c.int) -> c.int {
|
||||
return min(a, b)
|
||||
}
|
||||
|
||||
// @return the maximum of two integers
|
||||
@(deprecated="Prefer the built-in 'max(a, b)'", require_results)
|
||||
MaxInt :: proc "c" (a, b: c.int) -> c.int {
|
||||
return max(a, b)
|
||||
}
|
||||
|
||||
// @return the absolute value of an integer
|
||||
@(deprecated="Prefer the built-in 'abs(a)'", require_results)
|
||||
AbsInt :: proc "c" (a: c.int) -> c.int {
|
||||
return abs(a)
|
||||
}
|
||||
|
||||
// @return an integer clamped between a lower and upper bound
|
||||
@(deprecated="Prefer the built-in 'clamp(a, lower, upper)'", require_results)
|
||||
ClampInt :: proc "c" (a, lower, upper: c.int) -> c.int {
|
||||
return clamp(a, lower, upper)
|
||||
}
|
||||
|
||||
// Vector dot product
|
||||
@(require_results)
|
||||
Dot :: proc "c" (a, b: Vec2) -> f32 {
|
||||
return a.x * b.x + a.y * b.y
|
||||
}
|
||||
|
||||
// Vector cross product. In 2D this yields a scalar.
|
||||
@(require_results)
|
||||
Cross :: proc "c" (a, b: Vec2) -> f32 {
|
||||
return a.x * b.y - a.y * b.x
|
||||
}
|
||||
|
||||
// Perform the cross product on a vector and a scalar. In 2D this produces a vector.
|
||||
@(require_results)
|
||||
CrossVS :: proc "c" (v: Vec2, s: f32) -> Vec2 {
|
||||
return {s * v.y, -s * v.x}
|
||||
}
|
||||
|
||||
// Perform the cross product on a scalar and a vector. In 2D this produces a vector.
|
||||
@(require_results)
|
||||
CrossSV :: proc "c" (s: f32, v: Vec2) -> Vec2 {
|
||||
return {-s * v.y, s * v.x}
|
||||
}
|
||||
|
||||
// Get a left pointing perpendicular vector. Equivalent to b2CrossSV(1, v)
|
||||
@(require_results)
|
||||
LeftPerp :: proc "c" (v: Vec2) -> Vec2 {
|
||||
return {-v.y, v.x}
|
||||
}
|
||||
|
||||
// Get a right pointing perpendicular vector. Equivalent to b2CrossVS(v, 1)
|
||||
@(require_results)
|
||||
RightPerp :: proc "c" (v: Vec2) -> Vec2 {
|
||||
return {v.y, -v.x}
|
||||
}
|
||||
|
||||
// Vector addition
|
||||
@(deprecated="Prefer 'a + b'", require_results)
|
||||
Add :: proc "c" (a, b: Vec2) -> Vec2 {
|
||||
return a + b
|
||||
}
|
||||
|
||||
// Vector subtraction
|
||||
@(deprecated="Prefer 'a - b'", require_results)
|
||||
Sub :: proc "c" (a, b: Vec2) -> Vec2 {
|
||||
return a - b
|
||||
}
|
||||
|
||||
// Vector negation
|
||||
@(deprecated="Prefer '-a'", require_results)
|
||||
Neg :: proc "c" (a: Vec2) -> Vec2 {
|
||||
return -a
|
||||
}
|
||||
|
||||
// Vector linear interpolation
|
||||
// https://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/
|
||||
@(require_results)
|
||||
Lerp :: proc "c" (a, b: Vec2, t: f32) -> Vec2 {
|
||||
return {(1 - t) * a.x + t * b.x, (1 - t) * a.y + t * b.y}
|
||||
}
|
||||
|
||||
// Component-wise multiplication
|
||||
@(deprecated="Prefer 'a * b'", require_results)
|
||||
Mul :: proc "c" (a, b: Vec2) -> Vec2 {
|
||||
return a * b
|
||||
}
|
||||
|
||||
// Multiply a scalar and vector
|
||||
@(deprecated="Prefer 's * v'", require_results)
|
||||
MulSV :: proc "c" (s: f32, v: Vec2) -> Vec2 {
|
||||
return s * v
|
||||
}
|
||||
|
||||
// a + s * b
|
||||
@(deprecated="Prefer 'a + s * b'", require_results)
|
||||
MulAdd :: proc "c" (a: Vec2, s: f32, b: Vec2) -> Vec2 {
|
||||
return a + s * b
|
||||
}
|
||||
|
||||
// a - s * b
|
||||
@(deprecated="Prefer 'a - s * b'", require_results)
|
||||
MulSub :: proc "c" (a: Vec2, s: f32, b: Vec2) -> Vec2 {
|
||||
return a - s * b
|
||||
}
|
||||
|
||||
// Component-wise absolute vector
|
||||
@(require_results)
|
||||
Abs :: proc "c" (a: Vec2) -> (b: Vec2) {
|
||||
b.x = abs(a.x)
|
||||
b.y = abs(a.y)
|
||||
return
|
||||
}
|
||||
|
||||
// Component-wise minimum vector
|
||||
@(require_results)
|
||||
Min :: proc "c" (a, b: Vec2) -> (c: Vec2) {
|
||||
c.x = min(a.x, b.x)
|
||||
c.y = min(a.y, b.y)
|
||||
return
|
||||
}
|
||||
|
||||
// Component-wise maximum vector
|
||||
@(require_results)
|
||||
Max :: proc "c" (a, b: Vec2) -> (c: Vec2) {
|
||||
c.x = max(a.x, b.x)
|
||||
c.y = max(a.y, b.y)
|
||||
return
|
||||
}
|
||||
|
||||
// Component-wise clamp vector v into the range [a, b]
|
||||
@(require_results)
|
||||
Clamp :: proc "c" (v: Vec2, a, b: Vec2) -> (c: Vec2) {
|
||||
c.x = clamp(v.x, a.x, b.x)
|
||||
c.y = clamp(v.y, a.y, b.y)
|
||||
return
|
||||
}
|
||||
|
||||
// Get the length of this vector (the norm)
|
||||
@(require_results)
|
||||
Length :: proc "c" (v: Vec2) -> f32 {
|
||||
return math.sqrt(v.x * v.x + v.y * v.y)
|
||||
}
|
||||
|
||||
// Get the length squared of this vector
|
||||
@(require_results)
|
||||
LengthSquared :: proc "c" (v: Vec2) -> f32 {
|
||||
return v.x * v.x + v.y * v.y
|
||||
}
|
||||
|
||||
// Get the distance between two points
|
||||
@(require_results)
|
||||
Distance :: proc "c" (a, b: Vec2) -> f32 {
|
||||
dx := b.x - a.x
|
||||
dy := b.y - a.y
|
||||
return math.sqrt(dx * dx + dy * dy)
|
||||
}
|
||||
|
||||
// Get the distance squared between points
|
||||
@(require_results)
|
||||
DistanceSquared :: proc "c" (a, b: Vec2) -> f32 {
|
||||
c := Vec2{b.x - a.x, b.y - a.y}
|
||||
return c.x * c.x + c.y * c.y
|
||||
}
|
||||
|
||||
// Make a rotation using an angle in radians
|
||||
@(require_results)
|
||||
MakeRot :: proc "c" (angle: f32) -> Rot {
|
||||
// todo determinism
|
||||
return {math.cos(angle), math.sin(angle)}
|
||||
}
|
||||
|
||||
// Normalize rotation
|
||||
@(require_results)
|
||||
NormalizeRot :: proc "c" (q: Rot) -> Rot {
|
||||
mag := math.sqrt(q.s * q.s + q.c * q.c)
|
||||
invMag := f32(mag > 0.0 ? 1.0 / mag : 0.0)
|
||||
return {q.c * invMag, q.s * invMag}
|
||||
}
|
||||
|
||||
// Is this rotation normalized?
|
||||
@(require_results)
|
||||
IsNormalized :: proc "c" (q: Rot) -> bool {
|
||||
// larger tolerance due to failure on mingw 32-bit
|
||||
qq := q.s * q.s + q.c * q.c
|
||||
return 1.0 - 0.0006 < qq && qq < 1 + 0.0006
|
||||
}
|
||||
|
||||
// Normalized linear interpolation
|
||||
// https://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/
|
||||
@(require_results)
|
||||
NLerp :: proc "c" (q1: Rot, q2: Rot, t: f32) -> Rot {
|
||||
omt := 1 - t
|
||||
return NormalizeRot({
|
||||
omt * q1.c + t * q2.c,
|
||||
omt * q1.s + t * q2.s,
|
||||
})
|
||||
}
|
||||
|
||||
// Integration rotation from angular velocity
|
||||
// @param q1 initial rotation
|
||||
// @param deltaAngle the angular displacement in radians
|
||||
@(require_results)
|
||||
IntegrateRotation :: proc "c" (q1: Rot, deltaAngle: f32) -> Rot {
|
||||
// dc/dt = -omega * sin(t)
|
||||
// ds/dt = omega * cos(t)
|
||||
// c2 = c1 - omega * h * s1
|
||||
// s2 = s1 + omega * h * c1
|
||||
q2 := Rot{q1.c - deltaAngle * q1.s, q1.s + deltaAngle * q1.c}
|
||||
mag := math.sqrt(q2.s * q2.s + q2.c * q2.c)
|
||||
invMag := f32(mag > 0.0 ? 1 / mag : 0.0)
|
||||
return {q2.c * invMag, q2.s * invMag}
|
||||
}
|
||||
|
||||
// Compute the angular velocity necessary to rotate between two rotations over a give time
|
||||
// @param q1 initial rotation
|
||||
// @param q2 final rotation
|
||||
// @param inv_h inverse time step
|
||||
@(require_results)
|
||||
ComputeAngularVelocity :: proc "c" (q1: Rot, q2: Rot, inv_h: f32) -> f32 {
|
||||
// ds/dt = omega * cos(t)
|
||||
// dc/dt = -omega * sin(t)
|
||||
// s2 = s1 + omega * h * c1
|
||||
// c2 = c1 - omega * h * s1
|
||||
|
||||
// omega * h * s1 = c1 - c2
|
||||
// omega * h * c1 = s2 - s1
|
||||
// omega * h = (c1 - c2) * s1 + (s2 - s1) * c1
|
||||
// omega * h = s1 * c1 - c2 * s1 + s2 * c1 - s1 * c1
|
||||
// omega * h = s2 * c1 - c2 * s1 = sin(a2 - a1) ~= a2 - a1 for small delta
|
||||
omega := inv_h * (q2.s * q1.c - q2.c * q1.s)
|
||||
return omega
|
||||
}
|
||||
|
||||
// Get the angle in radians in the range [-pi, pi]
|
||||
@(require_results)
|
||||
Rot_GetAngle :: proc "c" (q: Rot) -> f32 {
|
||||
// todo determinism
|
||||
return math.atan2(q.s, q.c)
|
||||
}
|
||||
|
||||
// Get the x-axis
|
||||
@(require_results)
|
||||
Rot_GetXAxis :: proc "c" (q: Rot) -> Vec2 {
|
||||
return {q.c, q.s}
|
||||
}
|
||||
|
||||
// Get the y-axis
|
||||
@(require_results)
|
||||
Rot_GetYAxis :: proc "c" (q: Rot) -> Vec2 {
|
||||
return {-q.s, q.c}
|
||||
}
|
||||
|
||||
// Multiply two rotations: q * r
|
||||
@(require_results)
|
||||
MulRot :: proc "c" (q, r: Rot) -> (qr: Rot) {
|
||||
// [qc -qs] * [rc -rs] = [qc*rc-qs*rs -qc*rs-qs*rc]
|
||||
// [qs qc] [rs rc] [qs*rc+qc*rs -qs*rs+qc*rc]
|
||||
// s(q + r) = qs * rc + qc * rs
|
||||
// c(q + r) = qc * rc - qs * rs
|
||||
qr.s = q.s * r.c + q.c * r.s
|
||||
qr.c = q.c * r.c - q.s * r.s
|
||||
return
|
||||
}
|
||||
|
||||
// Transpose multiply two rotations: qT * r
|
||||
@(require_results)
|
||||
InvMulRot :: proc "c" (q, r: Rot) -> (qr: Rot) {
|
||||
// [ qc qs] * [rc -rs] = [qc*rc+qs*rs -qc*rs+qs*rc]
|
||||
// [-qs qc] [rs rc] [-qs*rc+qc*rs qs*rs+qc*rc]
|
||||
// s(q - r) = qc * rs - qs * rc
|
||||
// c(q - r) = qc * rc + qs * rs
|
||||
qr.s = q.c * r.s - q.s * r.c
|
||||
qr.c = q.c * r.c + q.s * r.s
|
||||
return
|
||||
}
|
||||
|
||||
// relative angle between b and a (rot_b * inv(rot_a))
|
||||
@(require_results)
|
||||
RelativeAngle :: proc "c" (b, a: Rot) -> f32 {
|
||||
// sin(b - a) = bs * ac - bc * as
|
||||
// cos(b - a) = bc * ac + bs * as
|
||||
s := b.s * a.c - b.c * a.s
|
||||
c := b.c * a.c + b.s * a.s
|
||||
return math.atan2(s, c)
|
||||
}
|
||||
|
||||
// Convert an angle in the range [-2*pi, 2*pi] into the range [-pi, pi]
|
||||
@(require_results)
|
||||
UnwindAngle :: proc "c" (angle: f32) -> f32 {
|
||||
if angle < -pi {
|
||||
return angle + 2.0 * pi
|
||||
} else if angle > pi {
|
||||
return angle - 2.0 * pi
|
||||
}
|
||||
return angle
|
||||
}
|
||||
|
||||
// Rotate a vector
|
||||
@(require_results)
|
||||
RotateVector :: proc "c" (q: Rot, v: Vec2) -> Vec2 {
|
||||
return {q.c * v.x - q.s * v.y, q.s * v.x + q.c * v.y}
|
||||
}
|
||||
|
||||
// Inverse rotate a vector
|
||||
@(require_results)
|
||||
InvRotateVector :: proc "c" (q: Rot, v: Vec2) -> Vec2 {
|
||||
return {q.c * v.x + q.s * v.y, -q.s * v.x + q.c * v.y}
|
||||
}
|
||||
|
||||
// Transform a point (e.g. local space to world space)
|
||||
@(require_results)
|
||||
TransformPoint :: proc "c" (t: Transform, p: Vec2) -> Vec2 {
|
||||
x := (t.q.c * p.x - t.q.s * p.y) + t.p.x
|
||||
y := (t.q.s * p.x + t.q.c * p.y) + t.p.y
|
||||
return {x, y}
|
||||
}
|
||||
|
||||
// Inverse transform a point (e.g. world space to local space)
|
||||
@(require_results)
|
||||
InvTransformPoint :: proc "c" (t: Transform, p: Vec2) -> Vec2 {
|
||||
vx := p.x - t.p.x
|
||||
vy := p.y - t.p.y
|
||||
return {t.q.c * vx + t.q.s * vy, -t.q.s * vx + t.q.c * vy}
|
||||
}
|
||||
|
||||
// v2 = A.q.Rot(B.q.Rot(v1) + B.p) + A.p
|
||||
// = (A.q * B.q).Rot(v1) + A.q.Rot(B.p) + A.p
|
||||
@(require_results)
|
||||
MulTransforms :: proc "c" (A, B: Transform) -> (C: Transform) {
|
||||
C.q = MulRot(A.q, B.q)
|
||||
C.p = RotateVector(A.q, B.p) + A.p
|
||||
return
|
||||
}
|
||||
|
||||
// v2 = A.q' * (B.q * v1 + B.p - A.p)
|
||||
// = A.q' * B.q * v1 + A.q' * (B.p - A.p)
|
||||
@(require_results)
|
||||
InvMulTransforms :: proc "c" (A, B: Transform) -> (C: Transform) {
|
||||
C.q = InvMulRot(A.q, B.q)
|
||||
C.p = InvRotateVector(A.q, B.p-A.p)
|
||||
return
|
||||
}
|
||||
|
||||
// Multiply a 2-by-2 matrix times a 2D vector
|
||||
@(deprecated="Prefer 'A * v'", require_results)
|
||||
MulMV :: proc "c" (A: Mat22, v: Vec2) -> Vec2 {
|
||||
return A * v
|
||||
}
|
||||
|
||||
// Get the inverse of a 2-by-2 matrix
|
||||
@(require_results)
|
||||
GetInverse22 :: proc "c" (A: Mat22) -> Mat22 {
|
||||
a := A[0, 0]
|
||||
b := A[0, 1]
|
||||
c := A[1, 0]
|
||||
d := A[1, 1]
|
||||
det := a * d - b * c
|
||||
if det != 0.0 {
|
||||
det = 1 / det
|
||||
}
|
||||
|
||||
return Mat22{
|
||||
det * d, -det * b,
|
||||
-det * c, det * a,
|
||||
}
|
||||
}
|
||||
|
||||
// Solve A * x = b, where b is a column vector. This is more efficient
|
||||
// than computing the inverse in one-shot cases.
|
||||
@(require_results)
|
||||
Solve22 :: proc "c" (A: Mat22, b: Vec2) -> Vec2 {
|
||||
a11 := A[0, 0]
|
||||
a12 := A[0, 1]
|
||||
a21 := A[1, 0]
|
||||
a22 := A[1, 1]
|
||||
det := a11 * a22 - a12 * a21
|
||||
if det != 0.0 {
|
||||
det = 1 / det
|
||||
}
|
||||
return {det * (a22 * b.x - a12 * b.y), det * (a11 * b.y - a21 * b.x)}
|
||||
}
|
||||
|
||||
// Does a fully contain b
|
||||
@(require_results)
|
||||
AABB_Contains :: proc "c" (a, b: AABB) -> bool {
|
||||
(a.lowerBound.x <= b.lowerBound.x) or_return
|
||||
(a.lowerBound.y <= b.lowerBound.y) or_return
|
||||
(b.upperBound.x <= a.upperBound.x) or_return
|
||||
(b.upperBound.y <= a.upperBound.y) or_return
|
||||
return true
|
||||
}
|
||||
|
||||
// Get the center of the AABB.
|
||||
@(require_results)
|
||||
AABB_Center :: proc "c" (a: AABB) -> Vec2 {
|
||||
return {0.5 * (a.lowerBound.x + a.upperBound.x), 0.5 * (a.lowerBound.y + a.upperBound.y)}
|
||||
}
|
||||
|
||||
// Get the extents of the AABB (half-widths).
|
||||
@(require_results)
|
||||
AABB_Extents :: proc "c" (a: AABB) -> Vec2 {
|
||||
return {0.5 * (a.upperBound.x - a.lowerBound.x), 0.5 * (a.upperBound.y - a.lowerBound.y)}
|
||||
}
|
||||
|
||||
// Union of two AABBs
|
||||
@(require_results)
|
||||
AABB_Union :: proc "c" (a, b: AABB) -> (c: AABB) {
|
||||
c.lowerBound.x = min(a.lowerBound.x, b.lowerBound.x)
|
||||
c.lowerBound.y = min(a.lowerBound.y, b.lowerBound.y)
|
||||
c.upperBound.x = max(a.upperBound.x, b.upperBound.x)
|
||||
c.upperBound.y = max(a.upperBound.y, b.upperBound.y)
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
Float_IsValid :: proc "c" (a: f32) -> bool {
|
||||
math.is_nan(a) or_return
|
||||
math.is_inf(a) or_return
|
||||
return true
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
Vec2_IsValid :: proc "c" (v: Vec2) -> bool {
|
||||
(math.is_nan(v.x) || math.is_nan(v.y)) or_return
|
||||
(math.is_inf(v.x) || math.is_inf(v.y)) or_return
|
||||
return true
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
Rot_IsValid :: proc "c" (q: Rot) -> bool {
|
||||
(math.is_nan(q.s) || math.is_nan(q.c)) or_return
|
||||
(math.is_inf(q.s) || math.is_inf(q.c)) or_return
|
||||
return IsNormalized(q)
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
Normalize :: proc "c" (v: Vec2) -> Vec2 {
|
||||
length := Length(v)
|
||||
if length < 1e-23 {
|
||||
return Vec2_zero
|
||||
}
|
||||
invLength := 1 / length
|
||||
return invLength * v
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
NormalizeChecked :: proc "odin" (v: Vec2) -> Vec2 {
|
||||
length := Length(v)
|
||||
if length < 1e-23 {
|
||||
panic("zero-length Vec2")
|
||||
}
|
||||
invLength := 1 / length
|
||||
return invLength * v
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
GetLengthAndNormalize :: proc "c" (v: Vec2) -> (length: f32, vn: Vec2) {
|
||||
length = Length(v)
|
||||
if length < 1e-23 {
|
||||
return
|
||||
}
|
||||
invLength := 1 / length
|
||||
vn = invLength * v
|
||||
return
|
||||
}
|
||||
Vendored
+1231
File diff suppressed because it is too large
Load Diff
Vendored
+22
-22
@@ -168,7 +168,7 @@ buffer :: struct {
|
||||
data_free_method: data_free_method,
|
||||
extras: extras_t,
|
||||
extensions_count: uint,
|
||||
extensions: [^]extension,
|
||||
extensions: [^]extension `fmt:"v,extensions_count"`,
|
||||
}
|
||||
|
||||
meshopt_compression_mode :: enum c.int {
|
||||
@@ -207,7 +207,7 @@ buffer_view :: struct {
|
||||
meshopt_compression: meshopt_compression,
|
||||
extras: extras_t,
|
||||
extensions_count: uint,
|
||||
extensions: [^]extension,
|
||||
extensions: [^]extension `fmt:"v,extensions_count"`,
|
||||
}
|
||||
|
||||
accessor_sparse :: struct {
|
||||
@@ -221,11 +221,11 @@ accessor_sparse :: struct {
|
||||
indices_extras: extras_t,
|
||||
values_extras: extras_t,
|
||||
extensions_count: uint,
|
||||
extensions: [^]extension,
|
||||
extensions: [^]extension `fmt:"v,extensions_count"`,
|
||||
indices_extensions_count: uint,
|
||||
indices_extensions: [^]extension,
|
||||
indices_extensions: [^]extension `fmt:"v,indices_extensions_count"`,
|
||||
values_extensions_count: uint,
|
||||
values_extensions: [^]extension,
|
||||
values_extensions: [^]extension `fmt:"v,values_extensions_count"`,
|
||||
}
|
||||
|
||||
accessor :: struct {
|
||||
@@ -245,7 +245,7 @@ accessor :: struct {
|
||||
sparse: accessor_sparse,
|
||||
extras: extras_t,
|
||||
extensions_count: uint,
|
||||
extensions: [^]extension,
|
||||
extensions: [^]extension `fmt:"v,extensions_count"`,
|
||||
}
|
||||
|
||||
attribute :: struct {
|
||||
@@ -262,7 +262,7 @@ image :: struct {
|
||||
mime_type: cstring,
|
||||
extras: extras_t,
|
||||
extensions_count: uint,
|
||||
extensions: [^]extension,
|
||||
extensions: [^]extension `fmt:"v,extensions_count"`,
|
||||
}
|
||||
|
||||
sampler :: struct {
|
||||
@@ -273,7 +273,7 @@ sampler :: struct {
|
||||
wrap_t: c.int,
|
||||
extras: extras_t,
|
||||
extensions_count: uint,
|
||||
extensions: [^]extension,
|
||||
extensions: [^]extension `fmt:"v,extensions_count"`,
|
||||
}
|
||||
|
||||
texture :: struct {
|
||||
@@ -284,7 +284,7 @@ texture :: struct {
|
||||
basisu_image: ^image,
|
||||
extras: extras_t,
|
||||
extensions_count: uint,
|
||||
extensions: [^]extension,
|
||||
extensions: [^]extension `fmt:"v,extensions_count"`,
|
||||
}
|
||||
|
||||
texture_transform :: struct {
|
||||
@@ -303,7 +303,7 @@ texture_view :: struct {
|
||||
transform: texture_transform,
|
||||
extras: extras_t,
|
||||
extensions_count: uint,
|
||||
extensions: [^]extension,
|
||||
extensions: [^]extension `fmt:"v,extensions_count"`,
|
||||
}
|
||||
|
||||
pbr_metallic_roughness :: struct {
|
||||
@@ -408,7 +408,7 @@ material :: struct {
|
||||
unlit: b32,
|
||||
extras: extras_t,
|
||||
extensions_count: uint,
|
||||
extensions: [^]extension,
|
||||
extensions: [^]extension `fmt:"v,extensions_count"`,
|
||||
}
|
||||
|
||||
material_mapping :: struct {
|
||||
@@ -442,7 +442,7 @@ primitive :: struct {
|
||||
draco_mesh_compression: draco_mesh_compression,
|
||||
mappings: []material_mapping,
|
||||
extensions_count: uint,
|
||||
extensions: [^]extension,
|
||||
extensions: [^]extension `fmt:"v,extensions_count"`,
|
||||
}
|
||||
|
||||
mesh :: struct {
|
||||
@@ -452,7 +452,7 @@ mesh :: struct {
|
||||
target_names: []cstring,
|
||||
extras: extras_t,
|
||||
extensions_count: uint,
|
||||
extensions: [^]extension,
|
||||
extensions: [^]extension `fmt:"v,extensions_count"`,
|
||||
}
|
||||
|
||||
skin :: struct {
|
||||
@@ -462,7 +462,7 @@ skin :: struct {
|
||||
inverse_bind_matrices: ^accessor,
|
||||
extras: extras_t,
|
||||
extensions_count: uint,
|
||||
extensions: [^]extension,
|
||||
extensions: [^]extension `fmt:"v,extensions_count"`,
|
||||
}
|
||||
|
||||
camera_perspective :: struct {
|
||||
@@ -492,7 +492,7 @@ camera :: struct {
|
||||
},
|
||||
extras: extras_t,
|
||||
extensions_count: uint,
|
||||
extensions: [^]extension,
|
||||
extensions: [^]extension `fmt:"v,extensions_count"`,
|
||||
}
|
||||
|
||||
light :: struct {
|
||||
@@ -527,7 +527,7 @@ node :: struct {
|
||||
has_mesh_gpu_instancing: b32,
|
||||
mesh_gpu_instancing: mesh_gpu_instancing,
|
||||
extensions_count: uint,
|
||||
extensions: [^]extension,
|
||||
extensions: [^]extension `fmt:"v,extensions_count"`,
|
||||
}
|
||||
|
||||
scene :: struct {
|
||||
@@ -535,7 +535,7 @@ scene :: struct {
|
||||
nodes: []^node,
|
||||
extras: extras_t,
|
||||
extensions_count: uint,
|
||||
extensions: [^]extension,
|
||||
extensions: [^]extension `fmt:"v,extensions_count"`,
|
||||
}
|
||||
|
||||
animation_sampler :: struct {
|
||||
@@ -544,7 +544,7 @@ animation_sampler :: struct {
|
||||
interpolation: interpolation_type,
|
||||
extras: extras_t,
|
||||
extensions_count: uint,
|
||||
extensions: [^]extension,
|
||||
extensions: [^]extension `fmt:"v,extensions_count"`,
|
||||
}
|
||||
|
||||
animation_channel :: struct {
|
||||
@@ -553,7 +553,7 @@ animation_channel :: struct {
|
||||
target_path: animation_path_type,
|
||||
extras: extras_t,
|
||||
extensions_count: uint,
|
||||
extensions: [^]extension,
|
||||
extensions: [^]extension `fmt:"v,extensions_count"`,
|
||||
}
|
||||
|
||||
animation :: struct {
|
||||
@@ -562,7 +562,7 @@ animation :: struct {
|
||||
channels: []animation_channel,
|
||||
extras: extras_t,
|
||||
extensions_count: uint,
|
||||
extensions: [^]extension,
|
||||
extensions: [^]extension `fmt:"v,extensions_count"`,
|
||||
}
|
||||
|
||||
material_variant :: struct {
|
||||
@@ -577,7 +577,7 @@ asset :: struct {
|
||||
min_version: cstring,
|
||||
extras: extras_t,
|
||||
extensions_count: uint,
|
||||
extensions: [^]extension,
|
||||
extensions: [^]extension `fmt:"v,extensions_count"`,
|
||||
}
|
||||
|
||||
data :: struct {
|
||||
@@ -609,7 +609,7 @@ data :: struct {
|
||||
extras: extras_t,
|
||||
|
||||
data_extensions_count: uint,
|
||||
data_extensions: [^]extension,
|
||||
data_extensions: [^]extension `fmt:"v,extensions_count"`,
|
||||
|
||||
extensions_used: []cstring,
|
||||
extensions_required: []cstring,
|
||||
|
||||
Vendored
+1
-1
@@ -338,7 +338,7 @@ foreign lib {
|
||||
node_set_list_tight :: proc(node: ^Node, tight: b32) -> (success: b32) ---
|
||||
|
||||
// Returns the info string from a fenced code block.
|
||||
get_fence_info :: proc(node: ^Node) -> (fence_info: cstring) ---
|
||||
node_get_fence_info :: proc(node: ^Node) -> (fence_info: cstring) ---
|
||||
|
||||
// Sets the info string in a fenced code block, returning `true` on success and `false` on failure.
|
||||
node_set_fence_info :: proc(node: ^Node, fence_info: cstring) -> (success: b32) ---
|
||||
|
||||
Vendored
+4
-4
@@ -3459,10 +3459,10 @@ DRED_DEVICE_STATE :: enum i32 {
|
||||
}
|
||||
|
||||
DRED_PAGE_FAULT_OUTPUT2 :: struct {
|
||||
PageFaultVA: GPU_VIRTUAL_ADDRESS,
|
||||
pHeadExistingAllocationNode: ^DRED_ALLOCATION_NODE1,
|
||||
pHeadRecentFreedAllocationNode: ^DRED_ALLOCATION_NODE1,
|
||||
PageFaultFlags: DRED_PAGE_FAULT_FLAGS,
|
||||
PageFaultVA: GPU_VIRTUAL_ADDRESS,
|
||||
pHeadExistingAllocationNode: ^DRED_ALLOCATION_NODE1,
|
||||
pHeadRecentFreedAllocationNode: ^DRED_ALLOCATION_NODE1,
|
||||
PageFaultFlags: DRED_PAGE_FAULT_FLAGS,
|
||||
}
|
||||
|
||||
DEVICE_REMOVED_EXTENDED_DATA1 :: struct {
|
||||
|
||||
Vendored
+2
-2
@@ -476,8 +476,8 @@ IVersionInfo3_VTable :: struct {
|
||||
}
|
||||
|
||||
ArgPair :: struct {
|
||||
pName: wstring,
|
||||
pValue: wstring,
|
||||
pName: wstring,
|
||||
pValue: wstring,
|
||||
}
|
||||
|
||||
IPdbUtils_UUID_STRING :: "E6C9647E-9D6A-4C3B-B94C-524B5A6C343D"
|
||||
|
||||
Vendored
+25
-6
@@ -8,25 +8,38 @@ Surface :: distinct rawptr
|
||||
Config :: distinct rawptr
|
||||
Context :: distinct rawptr
|
||||
|
||||
Boolean :: b32
|
||||
|
||||
FALSE :: false
|
||||
TRUE :: true
|
||||
|
||||
NO_DISPLAY :: Display(uintptr(0))
|
||||
NO_CONTEXT :: Context(uintptr(0))
|
||||
NO_SURFACE :: Surface(uintptr(0))
|
||||
|
||||
DEFAULT_DISPLAY :: NativeDisplayType(uintptr(0))
|
||||
|
||||
CONTEXT_OPENGL_CORE_PROFILE_BIT :: 0x00000001
|
||||
WINDOW_BIT :: 0x0004
|
||||
OPENGL_BIT :: 0x0008
|
||||
OPENGL_ES2_BIT :: 0x0004
|
||||
OPENGL_ES3_BIT :: 0x00000040
|
||||
|
||||
ALPHA_SIZE :: 0x3021
|
||||
BLUE_SIZE :: 0x3022
|
||||
GREEN_SIZE :: 0x3023
|
||||
RED_SIZE :: 0x3024
|
||||
DEPTH_SIZE :: 0x3025
|
||||
STENCIL_SIZE :: 0x3026
|
||||
NATIVE_VISUAL_ID :: 0x302E
|
||||
|
||||
SURFACE_TYPE :: 0x3033
|
||||
NONE :: 0x3038
|
||||
COLOR_BUFFER_TYPE :: 0x303F
|
||||
RENDERABLE_TYPE :: 0x3040
|
||||
CONFORMANT :: 0x3042
|
||||
HEIGHT :: 0x3056
|
||||
WIDTH :: 0x3057
|
||||
|
||||
BACK_BUFFER :: 0x3084
|
||||
RENDER_BUFFER :: 0x3086
|
||||
@@ -35,6 +48,7 @@ GL_COLORSPACE_LINEAR :: 0x308A
|
||||
RGB_BUFFER :: 0x308E
|
||||
GL_COLORSPACE :: 0x309D
|
||||
|
||||
CONTEXT_CLIENT_VERSION :: 0x3098
|
||||
CONTEXT_MAJOR_VERSION :: 0x3098
|
||||
CONTEXT_MINOR_VERSION :: 0x30FB
|
||||
CONTEXT_OPENGL_PROFILE_MASK :: 0x30FD
|
||||
@@ -45,15 +59,20 @@ foreign import egl "system:EGL"
|
||||
@(default_calling_convention="c", link_prefix="egl")
|
||||
foreign egl {
|
||||
GetDisplay :: proc(display: NativeDisplayType) -> Display ---
|
||||
Initialize :: proc(display: Display, major: ^i32, minor: ^i32) -> i32 ---
|
||||
BindAPI :: proc(api: u32) -> i32 ---
|
||||
ChooseConfig :: proc(display: Display, attrib_list: ^i32, configs: ^Config, config_size: i32, num_config: ^i32) -> i32 ---
|
||||
Initialize :: proc(display: Display, major: ^i32, minor: ^i32) -> Boolean ---
|
||||
BindAPI :: proc(api: u32) -> Boolean ---
|
||||
ChooseConfig :: proc(display: Display, attrib_list: ^i32, configs: ^Config, config_size: i32, num_config: ^i32) -> Boolean ---
|
||||
CreateWindowSurface :: proc(display: Display, config: Config, native_window: NativeWindowType, attrib_list: ^i32) -> Surface ---
|
||||
CreateContext :: proc(display: Display, config: Config, share_context: Context, attrib_list: ^i32) -> Context ---
|
||||
MakeCurrent :: proc(display: Display, draw: Surface, read: Surface, ctx: Context) -> i32 ---
|
||||
SwapInterval :: proc(display: Display, interval: i32) -> i32 ---
|
||||
SwapBuffers :: proc(display: Display, surface: Surface) -> i32 ---
|
||||
MakeCurrent :: proc(display: Display, draw: Surface, read: Surface, ctx: Context) -> Boolean ---
|
||||
QuerySurface :: proc(display: Display, surface: Surface, attribute: i32, value: ^i32) -> Boolean ---
|
||||
SwapInterval :: proc(display: Display, interval: i32) -> Boolean ---
|
||||
SwapBuffers :: proc(display: Display, surface: Surface) -> Boolean ---
|
||||
GetProcAddress :: proc(name: cstring) -> rawptr ---
|
||||
GetConfigAttrib :: proc(display: Display, config: Config, attribute: i32, value: ^i32) -> Boolean ---
|
||||
DestroyContext :: proc(display: Display, ctx: Context) -> Boolean ---
|
||||
DestroySurface :: proc(display: Display, surface: Surface) -> Boolean ---
|
||||
Terminate :: proc(display: Display) -> Boolean ---
|
||||
}
|
||||
|
||||
gl_set_proc_address :: proc(p: rawptr, name: cstring) {
|
||||
|
||||
Vendored
+260
-304
@@ -1,3 +1,15 @@
|
||||
/*
|
||||
Created in 2009, the GGPO networking SDK pioneered the use of rollback networking in peer-to-peer games.
|
||||
It's designed specifically to hide network latency in fast paced, twitch style games which require very
|
||||
precise inputs and frame perfect execution.
|
||||
|
||||
Traditional techniques account for network transmission time by adding delay to a players input, resulting
|
||||
in a sluggish, laggy game-feel. Rollback networking uses input prediction and speculative execution to
|
||||
send player inputs to the game immediately, providing the illusion of a zero-latency network. Using rollback,
|
||||
the same timings, reactions visual and audio queues, and muscle memory your players build up playing offline
|
||||
translate directly online. The GGPO networking SDK is designed to make incorporating rollback networking
|
||||
into new and existing games as easy as possible.
|
||||
*/
|
||||
package vendor_ggpo
|
||||
|
||||
foreign import lib "GGPO.lib"
|
||||
@@ -19,31 +31,27 @@ PlayerType :: enum c.int {
|
||||
SPECTATOR,
|
||||
}
|
||||
|
||||
/*
|
||||
* The Player structure used to describe players in add_player
|
||||
*
|
||||
* size: Should be set to the size_of(Player)
|
||||
*
|
||||
* type: One of the PlayerType values describing how inputs should be handled
|
||||
* Local players must have their inputs updated every frame via
|
||||
* add_local_inputs. Remote players values will come over the
|
||||
* network.
|
||||
*
|
||||
* player_num: The player number. Should be between 1 and the number of players
|
||||
* In the game (e.g. in a 2 player game, either 1 or 2).
|
||||
*
|
||||
* If type == PLAYERTYPE_REMOTE:
|
||||
*
|
||||
* remote.ip_address: The ip address of the ggpo session which will host this
|
||||
* player.
|
||||
*
|
||||
* remote.port: The port where udp packets should be sent to reach this player.
|
||||
* All the local inputs for this session will be sent to this player at
|
||||
* ip_address:port.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// The Player structure used to describe players in add_player
|
||||
//
|
||||
// size: Should be set to the size_of(Player)
|
||||
//
|
||||
// type: One of the PlayerType values describing how inputs should be handled
|
||||
// Local players must have their inputs updated every frame via
|
||||
// add_local_inputs. Remote players values will come over the
|
||||
// network.
|
||||
//
|
||||
// player_num: The player number. Should be between 1 and the number of players
|
||||
// In the game (e.g. in a 2 player game, either 1 or 2).
|
||||
//
|
||||
// If type == PLAYERTYPE_REMOTE:
|
||||
//
|
||||
// remote.ip_address: The ip address of the ggpo session which will host this
|
||||
// player.
|
||||
//
|
||||
// remote.port: The port where udp packets should be sent to reach this player.
|
||||
// All the local inputs for this session will be sent to this player at
|
||||
// ip_address:port.
|
||||
Player :: struct {
|
||||
size: c.int,
|
||||
type: PlayerType,
|
||||
@@ -80,32 +88,29 @@ ErrorCode :: enum c.int {
|
||||
|
||||
INVALID_HANDLE :: PlayerHandle(-1)
|
||||
|
||||
/*
|
||||
* The EventCode enumeration describes what type of event just happened.
|
||||
*
|
||||
* CONNECTED_TO_PEER - Handshake with the game running on the
|
||||
* other side of the network has been completed.
|
||||
*
|
||||
* SYNCHRONIZING_WITH_PEER - Beginning the synchronization
|
||||
* process with the client on the other end of the networking. The count
|
||||
* and total fields in the u.synchronizing struct of the Event
|
||||
* object indicate progress.
|
||||
*
|
||||
* SYNCHRONIZED_WITH_PEER - The synchronziation with this
|
||||
* peer has finished.
|
||||
*
|
||||
* RUNNING - All the clients have synchronized. You may begin
|
||||
* sending inputs with synchronize_inputs.
|
||||
*
|
||||
* DISCONNECTED_FROM_PEER - The network connection on
|
||||
* the other end of the network has closed.
|
||||
*
|
||||
* TIMESYNC - The time synchronziation code has determined
|
||||
* that this client is too far ahead of the other one and should slow
|
||||
* down to ensure fairness. The u.timesync.frames_ahead parameter in
|
||||
* the Event object indicates how many frames the client is.
|
||||
*
|
||||
*/
|
||||
// The EventCode enumeration describes what type of event just happened.
|
||||
//
|
||||
// CONNECTED_TO_PEER - Handshake with the game running on the
|
||||
// other side of the network has been completed.
|
||||
//
|
||||
// SYNCHRONIZING_WITH_PEER - Beginning the synchronization
|
||||
// process with the client on the other end of the networking. The count
|
||||
// and total fields in the u.synchronizing struct of the Event
|
||||
// object indicate progress.
|
||||
//
|
||||
// SYNCHRONIZED_WITH_PEER - The synchronziation with this
|
||||
// peer has finished.
|
||||
//
|
||||
// RUNNING - All the clients have synchronized. You may begin
|
||||
// sending inputs with synchronize_inputs.
|
||||
//
|
||||
// DISCONNECTED_FROM_PEER - The network connection on
|
||||
// the other end of the network has closed.
|
||||
//
|
||||
// TIMESYNC - The time synchronziation code has determined
|
||||
// that this client is too far ahead of the other one and should slow
|
||||
// down to ensure fairness. The u.timesync.frames_ahead parameter in
|
||||
// the Event object indicates how many frames the client is.
|
||||
EventCode :: enum c.int {
|
||||
CONNECTED_TO_PEER = 1000,
|
||||
SYNCHRONIZING_WITH_PEER = 1001,
|
||||
@@ -117,13 +122,10 @@ EventCode :: enum c.int {
|
||||
CONNECTION_RESUMED = 1007,
|
||||
}
|
||||
|
||||
/*
|
||||
* The Event structure contains an asynchronous event notification sent
|
||||
* by the on_event callback. See EventCode, above, for a detailed
|
||||
* explanation of each event.
|
||||
*/
|
||||
|
||||
Event :: struct {
|
||||
// The Event structure contains an asynchronous event notification sent
|
||||
// by the on_event callback. See EventCode, above, for a detailed
|
||||
// explanation of each event.
|
||||
Event :: struct {
|
||||
code: EventCode,
|
||||
using u: struct #raw_union {
|
||||
connected: struct {
|
||||
@@ -153,100 +155,83 @@ EventCode :: enum c.int {
|
||||
},
|
||||
}
|
||||
|
||||
/*
|
||||
* The SessionCallbacks structure contains the callback functions that
|
||||
* your application must implement. GGPO.net will periodically call these
|
||||
* functions during the game. All callback functions must be implemented.
|
||||
*/
|
||||
//
|
||||
// The SessionCallbacks structure contains the callback functions that
|
||||
// your application must implement. GGPO.net will periodically call these
|
||||
// functions during the game. All callback functions must be implemented.
|
||||
//
|
||||
SessionCallbacks :: struct {
|
||||
/*
|
||||
* begin_game callback - This callback has been deprecated. You must
|
||||
* implement it, but should ignore the 'game' parameter.
|
||||
*/
|
||||
// begin_game callback - This callback has been deprecated. You must
|
||||
// implement it, but should ignore the 'game' parameter.
|
||||
begin_game: proc "c" (game: cstring) -> bool,
|
||||
|
||||
/*
|
||||
* save_game_state - The client should allocate a buffer, copy the
|
||||
* entire contents of the current game state into it, and copy the
|
||||
* length into the len parameter. Optionally, the client can compute
|
||||
* a checksum of the data and store it in the checksum argument.
|
||||
*/
|
||||
// save_game_state - The client should allocate a buffer, copy the
|
||||
// entire contents of the current game state into it, and copy the
|
||||
// length into the len parameter. Optionally, the client can compute
|
||||
// a checksum of the data and store it in the checksum argument.
|
||||
save_game_state: proc "c" (buffer: ^[^]byte, len: ^c.int, checksum: ^c.int, frame: c.int) -> bool,
|
||||
|
||||
/*
|
||||
* load_game_state - GGPO.net will call this function at the beginning
|
||||
* of a rollback. The buffer and len parameters contain a previously
|
||||
* saved state returned from the save_game_state function. The client
|
||||
* should make the current game state match the state contained in the
|
||||
* buffer.
|
||||
*/
|
||||
// load_game_state - GGPO.net will call this function at the beginning
|
||||
// of a rollback. The buffer and len parameters contain a previously
|
||||
// saved state returned from the save_game_state function. The client
|
||||
// should make the current game state match the state contained in the
|
||||
// buffer.
|
||||
load_game_state: proc "c" (buffer: [^]byte, len: c.int) -> bool,
|
||||
|
||||
/*
|
||||
* log_game_state - Used in diagnostic testing. The client should use
|
||||
* the log function to write the contents of the specified save
|
||||
* state in a human readible form.
|
||||
*/
|
||||
// log_game_state - Used in diagnostic testing. The client should use
|
||||
// the log function to write the contents of the specified save
|
||||
// state in a human readible form.
|
||||
log_game_state: proc "c" (filename: cstring, buffer: [^]byte, len: c.int) -> bool,
|
||||
|
||||
/*
|
||||
* free_buffer - Frees a game state allocated in save_game_state. You
|
||||
* should deallocate the memory contained in the buffer.
|
||||
*/
|
||||
// free_buffer - Frees a game state allocated in save_game_state. You
|
||||
// should deallocate the memory contained in the buffer.
|
||||
free_buffer: proc "c" (buffer: rawptr),
|
||||
|
||||
/*
|
||||
* advance_frame - Called during a rollback. You should advance your game
|
||||
* state by exactly one frame. Before each frame, call synchronize_input
|
||||
* to retrieve the inputs you should use for that frame. After each frame,
|
||||
* you should call advance_frame to notify GGPO.net that you're
|
||||
* finished.
|
||||
*
|
||||
* The flags parameter is reserved. It can safely be ignored at this time.
|
||||
*/
|
||||
// advance_frame - Called during a rollback. You should advance your game
|
||||
// state by exactly one frame. Before each frame, call synchronize_input
|
||||
// to retrieve the inputs you should use for that frame. After each frame,
|
||||
// you should call advance_frame to notify GGPO.net that you're
|
||||
// finished.
|
||||
//
|
||||
// The flags parameter is reserved. It can safely be ignored at this time.
|
||||
advance_frame: proc "c" (flags: c.int) -> bool,
|
||||
|
||||
/*
|
||||
* on_event - Notification that something has happened. See the EventCode
|
||||
* structure above for more information.
|
||||
*/
|
||||
// on_event - Notification that something has happened. See the EventCode
|
||||
// structure above for more information.
|
||||
on_event: proc "c" (info: ^Event) -> bool,
|
||||
}
|
||||
|
||||
/*
|
||||
* The NetworkStats function contains some statistics about the current
|
||||
* session.
|
||||
*
|
||||
* network.send_queue_len - The length of the queue containing UDP packets
|
||||
* which have not yet been acknowledged by the end client. The length of
|
||||
* the send queue is a rough indication of the quality of the connection.
|
||||
* The longer the send queue, the higher the round-trip time between the
|
||||
* clients. The send queue will also be longer than usual during high
|
||||
* packet loss situations.
|
||||
*
|
||||
* network.recv_queue_len - The number of inputs currently buffered by the
|
||||
* GGPO.net network layer which have yet to be validated. The length of
|
||||
* the prediction queue is roughly equal to the current frame number
|
||||
* minus the frame number of the last packet in the remote queue.
|
||||
*
|
||||
* network.ping - The roundtrip packet transmission time as calcuated
|
||||
* by GGPO.net. This will be roughly equal to the actual round trip
|
||||
* packet transmission time + 2 the interval at which you call idle
|
||||
* or advance_frame.
|
||||
*
|
||||
* network.kbps_sent - The estimated bandwidth used between the two
|
||||
* clients, in kilobits per second.
|
||||
*
|
||||
* timesync.local_frames_behind - The number of frames GGPO.net calculates
|
||||
* that the local client is behind the remote client at this instant in
|
||||
* time. For example, if at this instant the current game client is running
|
||||
* frame 1002 and the remote game client is running frame 1009, this value
|
||||
* will mostly likely roughly equal 7.
|
||||
*
|
||||
* timesync.remote_frames_behind - The same as local_frames_behind, but
|
||||
* calculated from the perspective of the remote player.
|
||||
*
|
||||
*/
|
||||
// The NetworkStats function contains some statistics about the current
|
||||
// session.
|
||||
//
|
||||
// network.send_queue_len - The length of the queue containing UDP packets
|
||||
// which have not yet been acknowledged by the end client. The length of
|
||||
// the send queue is a rough indication of the quality of the connection.
|
||||
// The longer the send queue, the higher the round-trip time between the
|
||||
// clients. The send queue will also be longer than usual during high
|
||||
// packet loss situations.
|
||||
//
|
||||
// network.recv_queue_len - The number of inputs currently buffered by the
|
||||
// GGPO.net network layer which have yet to be validated. The length of
|
||||
// the prediction queue is roughly equal to the current frame number
|
||||
// minus the frame number of the last packet in the remote queue.
|
||||
//
|
||||
// network.ping - The roundtrip packet transmission time as calcuated
|
||||
// by GGPO.net. This will be roughly equal to the actual round trip
|
||||
// packet transmission time + 2 the interval at which you call idle
|
||||
// or advance_frame.
|
||||
//
|
||||
// network.kbps_sent - The estimated bandwidth used between the two
|
||||
// clients, in kilobits per second.
|
||||
//
|
||||
// timesync.local_frames_behind - The number of frames GGPO.net calculates
|
||||
// that the local client is behind the remote client at this instant in
|
||||
// time. For example, if at this instant the current game client is running
|
||||
// frame 1002 and the remote game client is running frame 1009, this value
|
||||
// will mostly likely roughly equal 7.
|
||||
//
|
||||
// timesync.remote_frames_behind - The same as local_frames_behind, but
|
||||
// calculated from the perspective of the remote player.
|
||||
NetworkStats :: struct {
|
||||
network: struct {
|
||||
send_queue_len: c.int,
|
||||
@@ -263,29 +248,27 @@ NetworkStats :: struct {
|
||||
@(default_calling_convention="c")
|
||||
@(link_prefix="ggpo_")
|
||||
foreign lib {
|
||||
/*
|
||||
* start_session --
|
||||
*
|
||||
* Used to being a new GGPO.net session. The ggpo object returned by start_session
|
||||
* uniquely identifies the state for this session and should be passed to all other
|
||||
* functions.
|
||||
*
|
||||
* session - An out parameter to the new ggpo session object.
|
||||
*
|
||||
* cb - A SessionCallbacks structure which contains the callbacks you implement
|
||||
* to help GGPO.net synchronize the two games. You must implement all functions in
|
||||
* cb, even if they do nothing but 'return true';
|
||||
*
|
||||
* game - The name of the game. This is used internally for GGPO for logging purposes only.
|
||||
*
|
||||
* num_players - The number of players which will be in this game. The number of players
|
||||
* per session is fixed. If you need to change the number of players or any player
|
||||
* disconnects, you must start a new session.
|
||||
*
|
||||
* input_size - The size of the game inputs which will be passsed to add_local_input.
|
||||
*
|
||||
* local_port - The port GGPO should bind to for UDP traffic.
|
||||
*/
|
||||
// start_session --
|
||||
//
|
||||
// Used to being a new GGPO.net session. The ggpo object returned by start_session
|
||||
// uniquely identifies the state for this session and should be passed to all other
|
||||
// functions.
|
||||
//
|
||||
// session - An out parameter to the new ggpo session object.
|
||||
//
|
||||
// cb - A SessionCallbacks structure which contains the callbacks you implement
|
||||
// to help GGPO.net synchronize the two games. You must implement all functions in
|
||||
// cb, even if they do nothing but 'return true';
|
||||
//
|
||||
// game - The name of the game. This is used internally for GGPO for logging purposes only.
|
||||
//
|
||||
// num_players - The number of players which will be in this game. The number of players
|
||||
// per session is fixed. If you need to change the number of players or any player
|
||||
// disconnects, you must start a new session.
|
||||
//
|
||||
// input_size - The size of the game inputs which will be passsed to add_local_input.
|
||||
//
|
||||
// local_port - The port GGPO should bind to for UDP traffic.
|
||||
start_session :: proc(session: ^^Session,
|
||||
cb: ^SessionCallbacks,
|
||||
game: cstring,
|
||||
@@ -294,17 +277,15 @@ foreign lib {
|
||||
localport: u16) -> ErrorCode ---
|
||||
|
||||
|
||||
/*
|
||||
* add_player --
|
||||
*
|
||||
* Must be called for each player in the session (e.g. in a 3 player session, must
|
||||
* be called 3 times).
|
||||
*
|
||||
* player - A Player struct used to describe the player.
|
||||
*
|
||||
* handle - An out parameter to a handle used to identify this player in the future.
|
||||
* (e.g. in the on_event callbacks).
|
||||
*/
|
||||
// add_player --
|
||||
//
|
||||
// Must be called for each player in the session (e.g. in a 3 player session, must
|
||||
// be called 3 times).
|
||||
//
|
||||
// player - A Player struct used to describe the player.
|
||||
//
|
||||
// handle - An out parameter to a handle used to identify this player in the future.
|
||||
// (e.g. in the on_event callbacks).
|
||||
add_player :: proc(session: ^Session,
|
||||
player: ^Player,
|
||||
handle: ^PlayerHandle) -> ErrorCode ---
|
||||
@@ -342,30 +323,28 @@ foreign lib {
|
||||
frames: c.int) -> ErrorCode ---
|
||||
|
||||
|
||||
/*
|
||||
* start_spectating --
|
||||
*
|
||||
* Start a spectator session.
|
||||
*
|
||||
* cb - A SessionCallbacks structure which contains the callbacks you implement
|
||||
* to help GGPO.net synchronize the two games. You must implement all functions in
|
||||
* cb, even if they do nothing but 'return true';
|
||||
*
|
||||
* game - The name of the game. This is used internally for GGPO for logging purposes only.
|
||||
*
|
||||
* num_players - The number of players which will be in this game. The number of players
|
||||
* per session is fixed. If you need to change the number of players or any player
|
||||
* disconnects, you must start a new session.
|
||||
*
|
||||
* input_size - The size of the game inputs which will be passsed to add_local_input.
|
||||
*
|
||||
* local_port - The port GGPO should bind to for UDP traffic.
|
||||
*
|
||||
* host_ip - The IP address of the host who will serve you the inputs for the game. Any
|
||||
* player partcipating in the session can serve as a host.
|
||||
*
|
||||
* host_port - The port of the session on the host
|
||||
*/
|
||||
// start_spectating --
|
||||
//
|
||||
// Start a spectator session.
|
||||
//
|
||||
// cb - A SessionCallbacks structure which contains the callbacks you implement
|
||||
// to help GGPO.net synchronize the two games. You must implement all functions in
|
||||
// cb, even if they do nothing but 'return true';
|
||||
//
|
||||
// game - The name of the game. This is used internally for GGPO for logging purposes only.
|
||||
//
|
||||
// num_players - The number of players which will be in this game. The number of players
|
||||
// per session is fixed. If you need to change the number of players or any player
|
||||
// disconnects, you must start a new session.
|
||||
//
|
||||
// input_size - The size of the game inputs which will be passsed to add_local_input.
|
||||
//
|
||||
// local_port - The port GGPO should bind to for UDP traffic.
|
||||
//
|
||||
// host_ip - The IP address of the host who will serve you the inputs for the game. Any
|
||||
// player partcipating in the session can serve as a host.
|
||||
//
|
||||
// host_port - The port of the session on the host
|
||||
start_spectating :: proc(session: ^^Session,
|
||||
cb: ^SessionCallbacks,
|
||||
game: cstring,
|
||||
@@ -375,152 +354,129 @@ foreign lib {
|
||||
host_ip: cstring,
|
||||
host_port: u16) -> ErrorCode ---
|
||||
|
||||
/*
|
||||
* close_session --
|
||||
* Used to close a session. You must call close_session to
|
||||
* free the resources allocated in start_session.
|
||||
*/
|
||||
// close_session --
|
||||
// Used to close a session. You must call close_session to
|
||||
// free the resources allocated in start_session.
|
||||
close_session :: proc(session: ^Session) -> ErrorCode ---
|
||||
|
||||
|
||||
/*
|
||||
* set_frame_delay --
|
||||
*
|
||||
* Change the amount of frames ggpo will delay local input. Must be called
|
||||
* before the first call to synchronize_input.
|
||||
*/
|
||||
// set_frame_delay --
|
||||
//
|
||||
// Change the amount of frames ggpo will delay local input. Must be called
|
||||
// before the first call to synchronize_input.
|
||||
set_frame_delay :: proc(session: ^Session,
|
||||
player: PlayerHandle,
|
||||
frame_delay: c.int) -> ErrorCode ---
|
||||
|
||||
/*
|
||||
* idle --
|
||||
* Should be called periodically by your application to give GGPO.net
|
||||
* a chance to do some work. Most packet transmissions and rollbacks occur
|
||||
* in idle.
|
||||
*
|
||||
* timeout - The amount of time GGPO.net is allowed to spend in this function,
|
||||
* in milliseconds.
|
||||
*/
|
||||
// idle --
|
||||
// Should be called periodically by your application to give GGPO.net
|
||||
// a chance to do some work. Most packet transmissions and rollbacks occur
|
||||
// in idle.
|
||||
//
|
||||
// timeout - The amount of time GGPO.net is allowed to spend in this function,
|
||||
// in milliseconds.
|
||||
idle :: proc(session: ^Session,
|
||||
timeout: c.int) -> ErrorCode ---
|
||||
|
||||
/*
|
||||
* add_local_input --
|
||||
*
|
||||
* Used to notify GGPO.net of inputs that should be trasmitted to remote
|
||||
* players. add_local_input must be called once every frame for
|
||||
* all player of type PLAYERTYPE_LOCAL.
|
||||
*
|
||||
* player - The player handle returned for this player when you called
|
||||
* add_local_player.
|
||||
*
|
||||
* values - The controller inputs for this player.
|
||||
*
|
||||
* size - The size of the controller inputs. This must be exactly equal to the
|
||||
* size passed into start_session.
|
||||
*/
|
||||
// add_local_input --
|
||||
//
|
||||
// Used to notify GGPO.net of inputs that should be trasmitted to remote
|
||||
// players. add_local_input must be called once every frame for
|
||||
// all player of type PLAYERTYPE_LOCAL.
|
||||
//
|
||||
// player - The player handle returned for this player when you called
|
||||
// add_local_player.
|
||||
//
|
||||
// values - The controller inputs for this player.
|
||||
//
|
||||
// size - The size of the controller inputs. This must be exactly equal to the
|
||||
// size passed into start_session.
|
||||
add_local_input :: proc(session: ^Session,
|
||||
player: PlayerHandle,
|
||||
values: rawptr,
|
||||
size: c.int) -> ErrorCode ---
|
||||
|
||||
/*
|
||||
* synchronize_input --
|
||||
*
|
||||
* You should call synchronize_input before every frame of execution,
|
||||
* including those frames which happen during rollback.
|
||||
*
|
||||
* values - When the function returns, the values parameter will contain
|
||||
* inputs for this frame for all players. The values array must be at
|
||||
* least (size * players) large.
|
||||
*
|
||||
* size - The size of the values array.
|
||||
*
|
||||
* disconnect_flags - Indicated whether the input in slot (1 << flag) is
|
||||
* valid. If a player has disconnected, the input in the values array for
|
||||
* that player will be zeroed and the i-th flag will be set. For example,
|
||||
* if only player 3 has disconnected, disconnect flags will be 8 (i.e. 1 << 3).
|
||||
*/
|
||||
// synchronize_input --
|
||||
//
|
||||
// You should call synchronize_input before every frame of execution,
|
||||
// including those frames which happen during rollback.
|
||||
//
|
||||
// values - When the function returns, the values parameter will contain
|
||||
// inputs for this frame for all players. The values array must be at
|
||||
// least (size * players) large.
|
||||
//
|
||||
// size - The size of the values array.
|
||||
//
|
||||
// disconnect_flags - Indicated whether the input in slot (1 << flag) is
|
||||
// valid. If a player has disconnected, the input in the values array for
|
||||
// that player will be zeroed and the i-th flag will be set. For example,
|
||||
// if only player 3 has disconnected, disconnect flags will be 8 (i.e. 1 << 3).
|
||||
synchronize_input :: proc(session: ^Session,
|
||||
values: rawptr,
|
||||
size: c.int,
|
||||
disconnect_flags: ^c.int) -> ErrorCode ---
|
||||
|
||||
/*
|
||||
* disconnect_player --
|
||||
*
|
||||
* Disconnects a remote player from a game. Will return ERRORCODE_PLAYER_DISCONNECTED
|
||||
* if you try to disconnect a player who has already been disconnected.
|
||||
*/
|
||||
// disconnect_player --
|
||||
//
|
||||
// Disconnects a remote player from a game. Will return ERRORCODE_PLAYER_DISCONNECTED
|
||||
// if you try to disconnect a player who has already been disconnected.
|
||||
disconnect_player :: proc(session: ^Session,
|
||||
player: PlayerHandle) -> ErrorCode ---
|
||||
|
||||
/*
|
||||
* advance_frame --
|
||||
*
|
||||
* You should call advance_frame to notify GGPO.net that you have
|
||||
* advanced your gamestate by a single frame. You should call this everytime
|
||||
* you advance the gamestate by a frame, even during rollbacks. GGPO.net
|
||||
* may call your save_state callback before this function returns.
|
||||
*/
|
||||
// advance_frame --
|
||||
//
|
||||
// You should call advance_frame to notify GGPO.net that you have
|
||||
// advanced your gamestate by a single frame. You should call this everytime
|
||||
// you advance the gamestate by a frame, even during rollbacks. GGPO.net
|
||||
// may call your save_state callback before this function returns.
|
||||
advance_frame :: proc(session: ^Session) -> ErrorCode ---
|
||||
|
||||
/*
|
||||
* get_network_stats --
|
||||
*
|
||||
* Used to fetch some statistics about the quality of the network connection.
|
||||
*
|
||||
* player - The player handle returned from the add_player function you used
|
||||
* to add the remote player.
|
||||
*
|
||||
* stats - Out parameter to the network statistics.
|
||||
*/
|
||||
// get_network_stats --
|
||||
//
|
||||
// Used to fetch some statistics about the quality of the network connection.
|
||||
//
|
||||
// player - The player handle returned from the add_player function you used
|
||||
// to add the remote player.
|
||||
//
|
||||
// stats - Out parameter to the network statistics.
|
||||
get_network_stats :: proc(session: ^Session,
|
||||
player: PlayerHandle,
|
||||
stats: ^NetworkStats) -> ErrorCode ---
|
||||
|
||||
/*
|
||||
* set_disconnect_timeout --
|
||||
*
|
||||
* Sets the disconnect timeout. The session will automatically disconnect
|
||||
* from a remote peer if it has not received a packet in the timeout window.
|
||||
* You will be notified of the disconnect via a EVENTCODE_DISCONNECTED_FROM_PEER
|
||||
* event.
|
||||
*
|
||||
* Setting a timeout value of 0 will disable automatic disconnects.
|
||||
*
|
||||
* timeout - The time in milliseconds to wait before disconnecting a peer.
|
||||
*/
|
||||
// set_disconnect_timeout --
|
||||
//
|
||||
// Sets the disconnect timeout. The session will automatically disconnect
|
||||
// from a remote peer if it has not received a packet in the timeout window.
|
||||
// You will be notified of the disconnect via a EVENTCODE_DISCONNECTED_FROM_PEER
|
||||
// event.
|
||||
//
|
||||
// Setting a timeout value of 0 will disable automatic disconnects.
|
||||
//
|
||||
// timeout - The time in milliseconds to wait before disconnecting a peer.
|
||||
set_disconnect_timeout :: proc(session: ^Session,
|
||||
timeout: c.int) -> ErrorCode ---
|
||||
|
||||
/*
|
||||
* set_disconnect_notify_start --
|
||||
*
|
||||
* The time to wait before the first EVENTCODE_NETWORK_INTERRUPTED timeout
|
||||
* will be sent.
|
||||
*
|
||||
* timeout - The amount of time which needs to elapse without receiving a packet
|
||||
* before the EVENTCODE_NETWORK_INTERRUPTED event is sent.
|
||||
*/
|
||||
// set_disconnect_notify_start --
|
||||
//
|
||||
// The time to wait before the first EVENTCODE_NETWORK_INTERRUPTED timeout
|
||||
// will be sent.
|
||||
//
|
||||
// timeout - The amount of time which needs to elapse without receiving a packet
|
||||
// before the EVENTCODE_NETWORK_INTERRUPTED event is sent.
|
||||
set_disconnect_notify_start :: proc(session: ^Session,
|
||||
timeout: c.int) -> ErrorCode ---
|
||||
|
||||
/*
|
||||
* log --
|
||||
*
|
||||
* Used to write to the ggpo.net log. In the current versions of the
|
||||
* SDK, a log file is only generated if the "quark.log" environment
|
||||
* variable is set to 1. This will change in future versions of the
|
||||
* SDK.
|
||||
*/
|
||||
// log --
|
||||
//
|
||||
// Used to write to the ggpo.net log. In the current versions of the
|
||||
// SDK, a log file is only generated if the "quark.log" environment
|
||||
// variable is set to 1. This will change in future versions of the
|
||||
// SDK.
|
||||
log :: proc(session: ^Session, fmt: cstring, #c_vararg args: ..any) ---
|
||||
/*
|
||||
* logv --
|
||||
*
|
||||
* A varargs compatible version of log. See log for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
// logv --
|
||||
//
|
||||
// A varargs compatible version of log. See log for
|
||||
// more details.
|
||||
logv :: proc(session: ^Session, fmt: cstring, args: c.va_list) ---
|
||||
}
|
||||
Vendored
+1
-1
@@ -575,7 +575,7 @@ PRELOAD_TABLE :: "_PRELOAD"
|
||||
|
||||
L_Reg :: struct {
|
||||
name: cstring,
|
||||
func: CFunction,
|
||||
func: CFunction,
|
||||
}
|
||||
|
||||
L_NUMSIZES :: size_of(Integer)*16 + size_of(Number)
|
||||
|
||||
Vendored
+3
-3
@@ -69,9 +69,9 @@ decoder :: struct {
|
||||
outputSampleRate: u32,
|
||||
converter: data_converter, /* <-- Data conversion is achieved by running frames through this. */
|
||||
pInputCache: rawptr, /* In input format. Can be null if it's not needed. */
|
||||
inputCacheCap: u64, /* The capacity of the input cache. */
|
||||
inputCacheConsumed: u64, /* The number of frames that have been consumed in the cache. Used for determining the next valid frame. */
|
||||
inputCacheRemaining: u64, /* The number of valid frames remaining in the cahce. */
|
||||
inputCacheCap: u64, /* The capacity of the input cache. */
|
||||
inputCacheConsumed: u64, /* The number of frames that have been consumed in the cache. Used for determining the next valid frame. */
|
||||
inputCacheRemaining: u64, /* The number of valid frames remaining in the cahce. */
|
||||
allocationCallbacks: allocation_callbacks,
|
||||
data: struct #raw_union {
|
||||
vfs: struct {
|
||||
|
||||
+3
-3
@@ -381,7 +381,7 @@ device_config :: struct {
|
||||
noPreSilencedOutputBuffer: b8, /* When set to true, the contents of the output buffer passed into the data callback will be left undefined rather than initialized to zero. */
|
||||
noClip: b8, /* When set to true, the contents of the output buffer passed into the data callback will not be clipped after returning. Only applies when the playback sample format is f32. */
|
||||
noDisableDenormals: b8, /* Do not disable denormals when firing the data callback. */
|
||||
noFixedSizedCallback: b8, /* Disables strict fixed-sized data callbacks. Setting this to true will result in the period size being treated only as a hint to the backend. This is an optimization for those who don't need fixed sized callbacks. */
|
||||
noFixedSizedCallback: b8, /* Disables strict fixed-sized data callbacks. Setting this to true will result in the period size being treated only as a hint to the backend. This is an optimization for those who don't need fixed sized callbacks. */
|
||||
dataCallback: device_data_proc,
|
||||
notificationCallback: device_notification_proc,
|
||||
stopCallback: stop_proc,
|
||||
@@ -813,7 +813,7 @@ context_type :: struct {
|
||||
/*pa_mainloop**/ pMainLoop: rawptr,
|
||||
/*pa_context**/ pPulseContext: rawptr,
|
||||
pApplicationName: cstring, /* Set when the context is initialized. Used by devices for their local pa_context objects. */
|
||||
pServerName: cstring, /* Set when the context is initialized. Used by devices for their local pa_context objects. */
|
||||
pServerName: cstring, /* Set when the context is initialized. Used by devices for their local pa_context objects. */
|
||||
} when SUPPORT_PULSEAUDIO else struct {}),
|
||||
|
||||
jack: (struct {
|
||||
@@ -1140,7 +1140,7 @@ device :: struct {
|
||||
|
||||
pulse: (struct {
|
||||
/*pa_mainloop**/ pMainLoop: rawptr,
|
||||
/*pa_context**/ pPulseContext: rawptr,
|
||||
/*pa_context**/ pPulseContext: rawptr,
|
||||
/*pa_stream**/ pStreamPlayback: rawptr,
|
||||
/*pa_stream**/ pStreamCapture: rawptr,
|
||||
} when SUPPORT_PULSEAUDIO else struct {}),
|
||||
|
||||
Vendored
+34
-32
@@ -80,9 +80,10 @@ foreign lib {
|
||||
HasHostError :: proc(stream: Stream) -> b32 ---
|
||||
}
|
||||
|
||||
/** Translate portmidi error number into human readable message.
|
||||
These strings are constants (set at compile time) so client has
|
||||
no need to allocate storage
|
||||
/**
|
||||
Translate portmidi error number into human readable message.
|
||||
These strings are constants (set at compile time) so client has
|
||||
no need to allocate storage
|
||||
*/
|
||||
GetErrorText :: proc (errnum: Error) -> string {
|
||||
@(default_calling_convention="c")
|
||||
@@ -92,9 +93,10 @@ GetErrorText :: proc (errnum: Error) -> string {
|
||||
return string(Pm_GetErrorText(errnum))
|
||||
}
|
||||
|
||||
/** Translate portmidi host error into human readable message.
|
||||
These strings are computed at run time, so client has to allocate storage.
|
||||
After this routine executes, the host error is cleared.
|
||||
/**
|
||||
Translate portmidi host error into human readable message.
|
||||
These strings are computed at run time, so client has to allocate storage.
|
||||
After this routine executes, the host error is cleared.
|
||||
*/
|
||||
GetHostErrorText :: proc (buf: []byte) -> string {
|
||||
@(default_calling_convention="c")
|
||||
@@ -133,8 +135,8 @@ foreign lib {
|
||||
|
||||
|
||||
/**
|
||||
Timestamp is used to represent a millisecond clock with arbitrary
|
||||
start time. The type is used for all MIDI timestampes and clocks.
|
||||
Timestamp is used to represent a millisecond clock with arbitrary
|
||||
start time. The type is used for all MIDI timestampes and clocks.
|
||||
*/
|
||||
Timestamp :: distinct i32
|
||||
TimeProc :: proc "c" (time_info: rawptr) -> Timestamp
|
||||
@@ -258,47 +260,47 @@ foreign lib {
|
||||
|
||||
/* Filter bit-mask definitions */
|
||||
/** filter active sensing messages (0xFE): */
|
||||
FILT_ACTIVE :: 1 << 0x0E
|
||||
FILT_ACTIVE :: 1 << 0x0E
|
||||
/** filter system exclusive messages (0xF0): */
|
||||
FILT_SYSEX :: 1 << 0x00
|
||||
FILT_SYSEX :: 1 << 0x00
|
||||
/** filter MIDI clock message (0xF8) */
|
||||
FILT_CLOCK :: 1 << 0x08
|
||||
FILT_CLOCK :: 1 << 0x08
|
||||
/** filter play messages (start 0xFA, stop 0xFC, continue 0xFB) */
|
||||
FILT_PLAY :: (1 << 0x0A) | (1 << 0x0C) | (1 << 0x0B)
|
||||
FILT_PLAY :: (1 << 0x0A) | (1 << 0x0C) | (1 << 0x0B)
|
||||
/** filter tick messages (0xF9) */
|
||||
FILT_TICK :: 1 << 0x09
|
||||
FILT_TICK :: 1 << 0x09
|
||||
/** filter undefined FD messages */
|
||||
FILT_FD :: 1 << 0x0D
|
||||
FILT_FD :: 1 << 0x0D
|
||||
/** filter undefined real-time messages */
|
||||
FILT_UNDEFINED :: FILT_FD
|
||||
FILT_UNDEFINED :: FILT_FD
|
||||
/** filter reset messages (0xFF) */
|
||||
FILT_RESET :: 1 << 0x0F
|
||||
FILT_RESET :: 1 << 0x0F
|
||||
/** filter all real-time messages */
|
||||
FILT_REALTIME :: FILT_ACTIVE | FILT_SYSEX | FILT_CLOCK | FILT_PLAY | FILT_UNDEFINED | FILT_RESET | FILT_TICK
|
||||
FILT_REALTIME :: FILT_ACTIVE | FILT_SYSEX | FILT_CLOCK | FILT_PLAY | FILT_UNDEFINED | FILT_RESET | FILT_TICK
|
||||
/** filter note-on and note-off (0x90-0x9F and 0x80-0x8F */
|
||||
FILT_NOTE :: (1 << 0x19) | (1 << 0x18)
|
||||
FILT_NOTE :: (1 << 0x19) | (1 << 0x18)
|
||||
/** filter channel aftertouch (most midi controllers use this) (0xD0-0xDF)*/
|
||||
FILT_CHANNEL_AFTERTOUCH :: 1 << 0x1D
|
||||
/** per-note aftertouch (0xA0-0xAF) */
|
||||
FILT_POLY_AFTERTOUCH :: 1 << 0x1A
|
||||
FILT_POLY_AFTERTOUCH :: 1 << 0x1A
|
||||
/** filter both channel and poly aftertouch */
|
||||
FILT_AFTERTOUCH :: FILT_CHANNEL_AFTERTOUCH | FILT_POLY_AFTERTOUCH
|
||||
FILT_AFTERTOUCH :: FILT_CHANNEL_AFTERTOUCH | FILT_POLY_AFTERTOUCH
|
||||
/** Program changes (0xC0-0xCF) */
|
||||
FILT_PROGRAM :: 1 << 0x1C
|
||||
FILT_PROGRAM :: 1 << 0x1C
|
||||
/** Control Changes (CC's) (0xB0-0xBF)*/
|
||||
FILT_CONTROL :: 1 << 0x1B
|
||||
FILT_CONTROL :: 1 << 0x1B
|
||||
/** Pitch Bender (0xE0-0xEF*/
|
||||
FILT_PITCHBEND :: 1 << 0x1E
|
||||
FILT_PITCHBEND :: 1 << 0x1E
|
||||
/** MIDI Time Code (0xF1)*/
|
||||
FILT_MTC :: 1 << 0x01
|
||||
FILT_MTC :: 1 << 0x01
|
||||
/** Song Position (0xF2) */
|
||||
FILT_SONG_POSITION :: 1 << 0x02
|
||||
FILT_SONG_POSITION :: 1 << 0x02
|
||||
/** Song Select (0xF3)*/
|
||||
FILT_SONG_SELECT :: 1 << 0x03
|
||||
FILT_SONG_SELECT :: 1 << 0x03
|
||||
/** Tuning request (0xF6)*/
|
||||
FILT_TUNE :: 1 << 0x06
|
||||
FILT_TUNE :: 1 << 0x06
|
||||
/** All System Common messages (mtc, song position, song select, tune request) */
|
||||
FILT_SYSTEMCOMMON :: FILT_MTC | FILT_SONG_POSITION | FILT_SONG_SELECT | FILT_TUNE
|
||||
FILT_SYSTEMCOMMON :: FILT_MTC | FILT_SONG_POSITION | FILT_SONG_SELECT | FILT_TUNE
|
||||
|
||||
Channel :: #force_inline proc "c" (channel: c.int) -> c.int {
|
||||
return 1<<c.uint(channel)
|
||||
@@ -367,11 +369,11 @@ foreign lib {
|
||||
}
|
||||
|
||||
/**
|
||||
MessageMake() encodes a short Midi message into a 32-bit word. If data1
|
||||
and/or data2 are not present, use zero.
|
||||
MessageMake() encodes a short Midi message into a 32-bit word. If data1
|
||||
and/or data2 are not present, use zero.
|
||||
|
||||
MessageStatus(), MessageData1(), and
|
||||
MessageData2() extract fields from a 32-bit midi message.
|
||||
MessageStatus(), MessageData1(), and
|
||||
MessageData2() extract fields from a 32-bit midi message.
|
||||
*/
|
||||
MessageMake :: #force_inline proc "c" (status: c.int, data1, data2: c.int) -> Message {
|
||||
return Message(((data2 << 16) & 0xFF0000) | ((data1 << 8) & 0xFF00) | (status & 0xFF))
|
||||
|
||||
Vendored
+5
-7
@@ -110,6 +110,8 @@ GuiDefaultProperty :: enum c.int {
|
||||
LINE_COLOR, // Line control color
|
||||
BACKGROUND_COLOR, // Background color
|
||||
TEXT_LINE_SPACING, // Text spacing between lines
|
||||
TEXT_ALIGNMENT_VERTICAL, // Text vertical alignment inside text bounds (after border and padding)
|
||||
TEXT_WRAP_MODE, // Text wrap-mode inside text bounds
|
||||
}
|
||||
|
||||
// Label
|
||||
@@ -163,11 +165,7 @@ GuiDropdownBoxProperty :: enum c.int {
|
||||
|
||||
// TextBox/TextBoxMulti/ValueBox/Spinner
|
||||
GuiTextBoxProperty :: enum c.int {
|
||||
TEXT_INNER_PADDING = 16, // TextBox/TextBoxMulti/ValueBox/Spinner inner text padding
|
||||
TEXT_LINES_SPACING, // TextBoxMulti lines separation
|
||||
TEXT_ALIGNMENT_VERTICAL, // TextBoxMulti vertical alignment: 0-CENTERED, 1-UP, 2-DOWN
|
||||
TEXT_MULTILINE, // TextBox supports multiple lines
|
||||
TEXT_WRAP_MODE, // TextBox wrap mode for multiline: 0-NO_WRAP, 1-CHAR_WRAP, 2-WORD_WRAP
|
||||
TEXT_READONLY = 16, // TextBox in read-only mode: 0-text editable, 1-text no-editable
|
||||
}
|
||||
|
||||
// Spinner
|
||||
@@ -229,8 +227,8 @@ foreign lib {
|
||||
|
||||
// Style set/get functions
|
||||
|
||||
GuiSetStyle :: proc(control: GuiControl, property: GuiControlProperty, value: c.int) --- // Set one style property
|
||||
GuiGetStyle :: proc(control: GuiControl, property: GuiControlProperty) -> c.int --- // Get one style property
|
||||
GuiSetStyle :: proc(control: GuiControl, property: c.int, value: c.int) --- // Set one style property
|
||||
GuiGetStyle :: proc(control: GuiControl, property: c.int) -> c.int --- // Get one style property
|
||||
|
||||
// Styles loading functions
|
||||
|
||||
|
||||
Vendored
+23
-8
@@ -84,7 +84,6 @@ package raylib
|
||||
import "core:c"
|
||||
import "core:fmt"
|
||||
import "core:mem"
|
||||
import "core:strings"
|
||||
|
||||
import "core:math/linalg"
|
||||
_ :: linalg
|
||||
@@ -447,9 +446,9 @@ VrStereoConfig :: struct #align(4) {
|
||||
|
||||
// File path list
|
||||
FilePathList :: struct {
|
||||
capacity: c.uint, // Filepaths max entries
|
||||
count: c.uint, // Filepaths entries count
|
||||
paths: [^]cstring, // Filepaths entries
|
||||
capacity: c.uint, // Filepaths max entries
|
||||
count: c.uint, // Filepaths entries count
|
||||
paths: [^]cstring, // Filepaths entries
|
||||
}
|
||||
|
||||
// Automation event
|
||||
@@ -1029,7 +1028,6 @@ foreign lib {
|
||||
SetTraceLogLevel :: proc(logLevel: TraceLogLevel) --- // Set the current threshold (minimum) log level
|
||||
MemAlloc :: proc(size: c.uint) -> rawptr --- // Internal memory allocator
|
||||
MemRealloc :: proc(ptr: rawptr, size: c.uint) -> rawptr --- // Internal memory reallocator
|
||||
MemFree :: proc(ptr: rawptr) --- // Internal memory free
|
||||
|
||||
// Set custom callbacks
|
||||
// WARNING: Callbacks setup is intended for advance users
|
||||
@@ -1256,7 +1254,7 @@ foreign lib {
|
||||
LoadImage :: proc(fileName: cstring) -> Image --- // Load image from file into CPU memory (RAM)
|
||||
LoadImageRaw :: proc(fileName: cstring, width, height: c.int, format: PixelFormat, headerSize: c.int) -> Image --- // Load image from RAW file data
|
||||
LoadImageSvg :: proc(fileNameOrString: cstring, width, height: c.int) -> Image --- // Load image from SVG file data or string with specified size
|
||||
LoadImageAnim :: proc(fileName: cstring, frames: [^]c.int) -> Image --- // Load image sequence from file (frames appended to image.data)
|
||||
LoadImageAnim :: proc(fileName: cstring, frames: ^c.int) -> Image --- // Load image sequence from file (frames appended to image.data)
|
||||
LoadImageFromMemory :: proc(fileType: cstring, fileData: rawptr, dataSize: c.int) -> Image --- // Load image from memory buffer, fileType refers to extension: i.e. '.png'
|
||||
LoadImageFromTexture :: proc(texture: Texture2D) -> Image --- // Load image from GPU texture data
|
||||
LoadImageFromScreen :: proc() -> Image --- // Load image from screen buffer and (screenshot)
|
||||
@@ -1684,8 +1682,25 @@ TextFormat :: proc(text: cstring, args: ..any) -> cstring {
|
||||
|
||||
// Text formatting with variables (sprintf style) and allocates (must be freed with 'MemFree')
|
||||
TextFormatAlloc :: proc(text: cstring, args: ..any) -> cstring {
|
||||
str := fmt.tprintf(string(text), ..args)
|
||||
return strings.clone_to_cstring(str, MemAllocator())
|
||||
return fmt.caprintf(string(text), ..args, allocator=MemAllocator())
|
||||
}
|
||||
|
||||
|
||||
// Internal memory free
|
||||
MemFree :: proc{
|
||||
MemFreePtr,
|
||||
MemFreeCstring,
|
||||
}
|
||||
|
||||
|
||||
@(default_calling_convention="c")
|
||||
foreign lib {
|
||||
@(link_name="MemFree")
|
||||
MemFreePtr :: proc(ptr: rawptr) ---
|
||||
}
|
||||
|
||||
MemFreeCstring :: proc "c" (s: cstring) {
|
||||
MemFreePtr(rawptr(s))
|
||||
}
|
||||
|
||||
|
||||
|
||||
Vendored
+6
@@ -41,6 +41,12 @@ MAJOR_VERSION :: 2
|
||||
MINOR_VERSION :: 0
|
||||
PATCHLEVEL :: 16
|
||||
|
||||
VERSION :: proc "contextless" (ver: ^version) {
|
||||
ver.major = MAJOR_VERSION
|
||||
ver.minor = MINOR_VERSION
|
||||
ver.patch = PATCHLEVEL
|
||||
}
|
||||
|
||||
@(default_calling_convention="c", link_prefix="SDL_")
|
||||
foreign lib {
|
||||
GetVersion :: proc(ver: ^version) ---
|
||||
|
||||
Vendored
+4
-4
@@ -171,9 +171,9 @@ KeyboardEvent :: struct {
|
||||
TEXTEDITINGEVENT_TEXT_SIZE :: 32
|
||||
TextEditingEvent :: struct {
|
||||
type: EventType, /**< ::SDL_TEXTEDITING */
|
||||
timestamp: u32, /**< In milliseconds, populated using SDL_GetTicks() */
|
||||
windowID: u32, /**< The window with keyboard focus, if any */
|
||||
text: [TEXTEDITINGEVENT_TEXT_SIZE]u8, /**< The editing text */
|
||||
timestamp: u32, /**< In milliseconds, populated using SDL_GetTicks() */
|
||||
windowID: u32, /**< The window with keyboard focus, if any */
|
||||
text: [TEXTEDITINGEVENT_TEXT_SIZE]u8, /**< The editing text */
|
||||
start: i32, /**< The start cursor of selected editing text */
|
||||
length: i32, /**< The length of selected editing text */
|
||||
}
|
||||
@@ -184,7 +184,7 @@ TextInputEvent :: struct {
|
||||
type: EventType, /**< ::SDL_TEXTINPUT */
|
||||
timestamp: u32, /**< In milliseconds, populated using SDL_GetTicks() */
|
||||
windowID: u32, /**< The window with keyboard focus, if any */
|
||||
text: [TEXTINPUTEVENT_TEXT_SIZE]u8, /**< The input text */
|
||||
text: [TEXTINPUTEVENT_TEXT_SIZE]u8, /**< The input text */
|
||||
}
|
||||
|
||||
MouseMotionEvent :: struct {
|
||||
|
||||
Vendored
+23
-23
@@ -54,29 +54,29 @@ GameControllerAxis :: enum c.int {
|
||||
}
|
||||
|
||||
GameControllerButton :: enum c.int {
|
||||
INVALID = -1,
|
||||
A,
|
||||
B,
|
||||
X,
|
||||
Y,
|
||||
BACK,
|
||||
GUIDE,
|
||||
START,
|
||||
LEFTSTICK,
|
||||
RIGHTSTICK,
|
||||
LEFTSHOULDER,
|
||||
RIGHTSHOULDER,
|
||||
DPAD_UP,
|
||||
DPAD_DOWN,
|
||||
DPAD_LEFT,
|
||||
DPAD_RIGHT,
|
||||
MISC1, /* Xbox Series X share button, PS5 microphone button, Nintendo Switch Pro capture button, Amazon Luna microphone button */
|
||||
PADDLE1, /* Xbox Elite paddle P1 */
|
||||
PADDLE2, /* Xbox Elite paddle P3 */
|
||||
PADDLE3, /* Xbox Elite paddle P2 */
|
||||
PADDLE4, /* Xbox Elite paddle P4 */
|
||||
TOUCHPAD, /* PS4/PS5 touchpad button */
|
||||
MAX,
|
||||
INVALID = -1,
|
||||
A,
|
||||
B,
|
||||
X,
|
||||
Y,
|
||||
BACK,
|
||||
GUIDE,
|
||||
START,
|
||||
LEFTSTICK,
|
||||
RIGHTSTICK,
|
||||
LEFTSHOULDER,
|
||||
RIGHTSHOULDER,
|
||||
DPAD_UP,
|
||||
DPAD_DOWN,
|
||||
DPAD_LEFT,
|
||||
DPAD_RIGHT,
|
||||
MISC1, /* Xbox Series X share button, PS5 microphone button, Nintendo Switch Pro capture button, Amazon Luna microphone button */
|
||||
PADDLE1, /* Xbox Elite paddle P1 */
|
||||
PADDLE2, /* Xbox Elite paddle P3 */
|
||||
PADDLE3, /* Xbox Elite paddle P2 */
|
||||
PADDLE4, /* Xbox Elite paddle P4 */
|
||||
TOUCHPAD, /* PS4/PS5 touchpad button */
|
||||
MAX,
|
||||
}
|
||||
|
||||
|
||||
|
||||
Vendored
+4
-4
@@ -19,10 +19,10 @@ TouchDeviceType :: enum c.int {
|
||||
}
|
||||
|
||||
Finger :: struct {
|
||||
id: FingerID,
|
||||
x: f32,
|
||||
y: f32,
|
||||
pressure: f32,
|
||||
id: FingerID,
|
||||
x: f32,
|
||||
y: f32,
|
||||
pressure: f32,
|
||||
}
|
||||
|
||||
TOUCH_MOUSEID :: ~u32(0)
|
||||
|
||||
+1
-1
@@ -166,7 +166,7 @@ datatype :: enum c.int {
|
||||
UINT32,
|
||||
FLOAT,
|
||||
|
||||
MAX_TYPES,
|
||||
MAX_TYPES,
|
||||
}
|
||||
|
||||
@(default_calling_convention="c", link_prefix="stbir_")
|
||||
|
||||
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
+1
-1
@@ -8,7 +8,7 @@ endif
|
||||
|
||||
wasm:
|
||||
mkdir -p ../lib
|
||||
clang -c -Os --target=wasm32 -nostdlib stb_truetype_wasm.c -o ../lib/stb_truetype_wasm.o
|
||||
$(CC) -c -Os --target=wasm32 -nostdlib stb_truetype_wasm.c -o ../lib/stb_truetype_wasm.o
|
||||
|
||||
unix:
|
||||
mkdir -p ../lib
|
||||
|
||||
Vendored
-3
@@ -1,5 +1,2 @@
|
||||
#define STB_RECT_PACK_IMPLEMENTATION
|
||||
#include "stb_rect_pack.h"
|
||||
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#include "stb_truetype.h"
|
||||
+1
-7
@@ -65,14 +65,8 @@ ceil :: proc "c" (x: f64) -> f64 { return math.ceil(x) }
|
||||
sqrt :: proc "c" (x: f64) -> f64 { return math.sqrt(x) }
|
||||
@(require, linkage="strong", link_name="stbtt_pow")
|
||||
pow :: proc "c" (x, y: f64) -> f64 { return math.pow(x, y) }
|
||||
|
||||
@(require, linkage="strong", link_name="stbtt_fmod")
|
||||
fmod :: proc "c" (x, y: f64) -> f64 {
|
||||
context = runtime.default_context()
|
||||
// NOTE: only called in the `stbtt_GetGlyphSDF` code path.
|
||||
panic("`math.round` is broken on 32 bit targets, see #3856")
|
||||
}
|
||||
|
||||
fmod :: proc "c" (x, y: f64) -> f64 { return math.mod(x, y) }
|
||||
@(require, linkage="strong", link_name="stbtt_cos")
|
||||
cos :: proc "c" (x: f64) -> f64 { return math.cos(x) }
|
||||
@(require, linkage="strong", link_name="stbtt_acos")
|
||||
|
||||
Vendored
+2
-2
@@ -11,8 +11,8 @@ Have a look at the `example/` directory for the rendering of a basic triangle.
|
||||
## Getting the wgpu-native libraries
|
||||
|
||||
For native support (not the browser), some libraries are required. Fortunately this is
|
||||
extremely easy, just download them from the [releases on GitHub](https://github.com/gfx-rs/wgpu-native/releases/tag/v0.19.4.1),
|
||||
the bindings are for v0.19.4.1 at the moment.
|
||||
extremely easy, just download them from the [releases on GitHub](https://github.com/gfx-rs/wgpu-native/releases/tag/v22.1.0.1),
|
||||
the bindings are for v22.1.0.1 at the moment.
|
||||
|
||||
These are expected in the `lib` folder under the same name as they are released (just unzipped).
|
||||
By default it will look for a static release version (`wgpu-OS-ARCH-release.a|lib`),
|
||||
|
||||
Vendored
+4
-2
@@ -158,15 +158,17 @@ frame :: proc "c" (dt: f32) {
|
||||
view = frame,
|
||||
loadOp = .Clear,
|
||||
storeOp = .Store,
|
||||
clearValue = { r = 0, g = 1, b = 0, a = 1 },
|
||||
depthSlice = wgpu.DEPTH_SLICE_UNDEFINED,
|
||||
clearValue = { 0, 1, 0, 1 },
|
||||
},
|
||||
},
|
||||
)
|
||||
defer wgpu.RenderPassEncoderRelease(render_pass_encoder)
|
||||
|
||||
wgpu.RenderPassEncoderSetPipeline(render_pass_encoder, state.pipeline)
|
||||
wgpu.RenderPassEncoderDraw(render_pass_encoder, vertexCount=3, instanceCount=1, firstVertex=0, firstInstance=0)
|
||||
|
||||
wgpu.RenderPassEncoderEnd(render_pass_encoder)
|
||||
wgpu.RenderPassEncoderRelease(render_pass_encoder)
|
||||
|
||||
command_buffer := wgpu.CommandEncoderFinish(command_encoder, nil)
|
||||
defer wgpu.CommandBufferRelease(command_buffer)
|
||||
|
||||
Vendored
+4
-2
@@ -158,15 +158,17 @@ frame :: proc "c" (dt: f32) {
|
||||
view = frame,
|
||||
loadOp = .Clear,
|
||||
storeOp = .Store,
|
||||
clearValue = { r = 0, g = 1, b = 0, a = 1 },
|
||||
depthSlice = wgpu.DEPTH_SLICE_UNDEFINED,
|
||||
clearValue = { 0, 1, 0, 1 },
|
||||
},
|
||||
},
|
||||
)
|
||||
defer wgpu.RenderPassEncoderRelease(render_pass_encoder)
|
||||
|
||||
wgpu.RenderPassEncoderSetPipeline(render_pass_encoder, state.pipeline)
|
||||
wgpu.RenderPassEncoderDraw(render_pass_encoder, vertexCount=3, instanceCount=1, firstVertex=0, firstInstance=0)
|
||||
|
||||
wgpu.RenderPassEncoderEnd(render_pass_encoder)
|
||||
wgpu.RenderPassEncoderRelease(render_pass_encoder)
|
||||
|
||||
command_buffer := wgpu.CommandEncoderFinish(command_encoder, nil)
|
||||
defer wgpu.CommandBufferRelease(command_buffer)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Vendored
+2
@@ -5,7 +5,9 @@ import "vendor:wgpu"
|
||||
|
||||
GetSurface :: proc(instance: wgpu.Instance, window: ^sdl2.Window) -> wgpu.Surface {
|
||||
window_info: sdl2.SysWMinfo
|
||||
sdl2.VERSION(&window_info.version)
|
||||
sdl2.GetWindowWMInfo(window, &window_info)
|
||||
|
||||
if window_info.subsystem == .WAYLAND {
|
||||
display := window_info.info.wl.display
|
||||
surface := window_info.info.wl.surface
|
||||
|
||||
Vendored
+91
-96
@@ -44,6 +44,7 @@ class WebGPUInterface {
|
||||
BlendFactor: ["zero", "one", "src", "one-minus-src", "src-alpha", "one-minus-src-alpha", "dst", "one-minus-dst", "dst-alpha", "one-minus-dst-alpha", "src-alpha-saturated", "constant", "one-minus-constant", ],
|
||||
PresentMode: ["fifo", "fifo-relaxed", "immediate", "mailbox", ],
|
||||
TextureAspect: ["all", "stencil-only", "depth-only"],
|
||||
DeviceLostReason: [undefined, "unknown", "destroyed"],
|
||||
};
|
||||
|
||||
/** @type {WebGPUObjectManager<{}>} */
|
||||
@@ -382,13 +383,19 @@ class WebGPUInterface {
|
||||
*/
|
||||
RenderPassColorAttachment(start) {
|
||||
const viewIdx = this.mem.loadPtr(start + 4);
|
||||
const resolveTargetIdx = this.mem.loadPtr(start + 8);
|
||||
const resolveTargetIdx = this.mem.loadPtr(start + 12);
|
||||
|
||||
let depthSlice = this.mem.loadU32(start + 8);
|
||||
if (depthSlice == 0xFFFFFFFF) { // DEPTH_SLICE_UNDEFINED.
|
||||
depthSlice = undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
view: viewIdx > 0 ? this.textureViews.get(viewIdx) : undefined,
|
||||
resolveTarget: resolveTargetIdx > 0 ? this.textureViews.get(resolveTargetIdx) : undefined,
|
||||
loadOp: this.enumeration("LoadOp", start + 12),
|
||||
storeOp: this.enumeration("StoreOp", start + 16),
|
||||
depthSlice: depthSlice,
|
||||
loadOp: this.enumeration("LoadOp", start + 16),
|
||||
storeOp: this.enumeration("StoreOp", start + 20),
|
||||
clearValue: this.Color(start + 24),
|
||||
};
|
||||
}
|
||||
@@ -950,14 +957,25 @@ class WebGPUInterface {
|
||||
|
||||
/**
|
||||
* @param {number} adapterIdx
|
||||
* @param {number} propertiesPtr
|
||||
* @param {number} infoPtr
|
||||
*/
|
||||
wgpuAdapterGetProperties: (adapterIdx, propertiesPtr) => {
|
||||
this.assert(propertiesPtr != 0);
|
||||
// Unknown adapter.
|
||||
this.mem.storeI32(propertiesPtr + 28, 3);
|
||||
wgpuAdapterGetInfo: (adapterIdx, infoPtr) => {
|
||||
this.assert(infoPtr != 0);
|
||||
|
||||
// WebGPU backend.
|
||||
this.mem.storeI32(propertiesPtr + 32, 2);
|
||||
this.mem.storeI32(infoPtr + 20, 2);
|
||||
// Unknown adapter.
|
||||
this.mem.storeI32(infoPtr + 24, 3);
|
||||
|
||||
// NOTE: I don't think getting the other fields in this struct is possible.
|
||||
// `adapter.requestAdapterInfo` is deprecated.
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {number} infoPtr
|
||||
*/
|
||||
wgpuAdapterInfoFreeMembers: (infoPtr) => {
|
||||
// NOTE: nothing to free.
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -970,50 +988,6 @@ class WebGPUInterface {
|
||||
return adapter.features.has(this.enums.FeatureName[featureInt]);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {number} adapterIdx
|
||||
* @param {number} callbackPtr
|
||||
* @param {0|number} userdata
|
||||
*/
|
||||
wgpuAdapterRequestAdapterInfo: async (adapterIdx, callbackPtr, userdata) => {
|
||||
const adapter = this.adapters.get(adapterIdx);
|
||||
const callback = this.mem.exports.__indirect_function_table.get(callbackPtr);
|
||||
|
||||
const info = await adapter.requestAdapterInfo();
|
||||
|
||||
const addr = this.mem.exports.wgpu_alloc(16);
|
||||
|
||||
const vendorLength = new TextEncoder().encode(info.vendor).length;
|
||||
const vendorAddr = this.mem.exports.wgpu_alloc(vendorLength);
|
||||
this.mem.storeString(vendorAddr, info.vendor);
|
||||
this.mem.storeI32(addr + 0, vendorAddr);
|
||||
|
||||
const architectureLength = new TextEncoder().encode(info.architecture).length;
|
||||
const architectureAddr = this.mem.exports.wgpu_alloc(architectureLength);
|
||||
this.mem.storeString(architectureAddr, info.architecture);
|
||||
this.mem.storeI32(addr + 4, architectureAddr);
|
||||
|
||||
|
||||
const deviceLength = new TextEncoder().encode(info.device).length;
|
||||
const deviceAddr = this.mem.exports.wgpu_alloc(deviceLength);
|
||||
this.mem.storeString(deviceAddr, info.device);
|
||||
this.mem.storeI32(addr + 8, deviceAddr);
|
||||
|
||||
|
||||
const descriptionLength = new TextEncoder().encode(info.description).length;
|
||||
const descriptionAddr = this.mem.exports.wgpu_alloc(descriptionLength);
|
||||
this.mem.storeString(descriptionAddr, info.description);
|
||||
this.mem.storeI32(addr + 12, descriptionAddr);
|
||||
|
||||
callback(addr, userdata);
|
||||
|
||||
this.mem.exports.wgpu_free(descriptionAddr);
|
||||
this.mem.exports.wgpu_free(deviceAddr);
|
||||
this.mem.exports.wgpu_free(architectureAddr);
|
||||
this.mem.exports.wgpu_free(vendorAddr);
|
||||
this.mem.exports.wgpu_free(addr);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {number} adapterIdx
|
||||
* @param {0|number} descriptorPtr
|
||||
@@ -1040,14 +1014,69 @@ class WebGPUInterface {
|
||||
};
|
||||
}
|
||||
|
||||
let device;
|
||||
let deviceIdx;
|
||||
try {
|
||||
const device = await adapter.requestDevice(descriptor);
|
||||
device = await adapter.requestDevice(descriptor);
|
||||
deviceIdx = this.devices.create(device);
|
||||
// NOTE: don't callback here, any errors that happen later will then be caught by the catch here.
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
callback(1, null, null, userdata);
|
||||
const messageLength = new TextEncoder().encode(e.message).length;
|
||||
const messageAddr = this.mem.exports.wgpu_alloc(messageLength + 1);
|
||||
this.mem.storeString(messageAddr, e.message);
|
||||
|
||||
callback(1, null, messageAddr, userdata);
|
||||
|
||||
this.mem.exports.wgpu_free(messageAddr);
|
||||
}
|
||||
|
||||
let callbacksPtr = descriptorPtr + 24 + this.mem.intSize;
|
||||
|
||||
const deviceLostCallbackPtr = this.mem.loadPtr(callbacksPtr);
|
||||
if (deviceLostCallbackPtr != 0) {
|
||||
const deviceLostUserData = this.mem.loadPtr(callbacksPtr) + 4;
|
||||
const deviceLostCallback = this.mem.exports.__indirect_function_table.get(deviceLostCallbackPtr);
|
||||
|
||||
device.lost.then((info) => {
|
||||
const reason = this.enums.DeviceLostReason.indexOf(info.reason);
|
||||
|
||||
const messageLength = new TextEncoder().encode(info.message).length;
|
||||
const messageAddr = this.mem.exports.wgpu_alloc(messageLength + 1);
|
||||
this.mem.storeString(messageAddr, info.message);
|
||||
|
||||
deviceLostCallback(reason, messageAddr, deviceLostUserData);
|
||||
|
||||
this.mem.exports.wgpu_free(messageAddr);
|
||||
});
|
||||
}
|
||||
callbacksPtr += 8;
|
||||
|
||||
// Skip over `nextInChain`.
|
||||
callbacksPtr += 4;
|
||||
|
||||
const uncapturedErrorCallbackPtr = this.mem.loadPtr(callbacksPtr);
|
||||
if (uncapturedErrorCallbackPtr != 0) {
|
||||
const uncapturedErrorUserData = this.mem.loadPtr(callbacksPtr + 4);
|
||||
const uncapturedErrorCallback = this.mem.exports.__indirect_function_table.get(uncapturedErrorCallbackPtr);
|
||||
|
||||
device.onuncapturederror = (ev) => {
|
||||
let status = 4; // Unknown
|
||||
if (ev.error instanceof GPUValidationError) {
|
||||
status = 1; // Validation
|
||||
} else if (ev.error instanceof GPUOutOfMemoryError) {
|
||||
status = 2; // OutOfMemory
|
||||
} else if (ev.error instanceof GPUInternalError) {
|
||||
status = 3; // Internal
|
||||
}
|
||||
|
||||
const messageLength = new TextEncoder().encode(ev.error.message).length;
|
||||
const messageAddr = this.mem.exports.wgpu_alloc(messageLength + 1);
|
||||
this.mem.storeString(messageAddr, ev.error.message);
|
||||
|
||||
uncapturedErrorCallback(status, messageAddr, uncapturedErrorUserData);
|
||||
|
||||
this.mem.exports.wgpu_free(messageAddr);
|
||||
};
|
||||
}
|
||||
|
||||
callback(0, deviceIdx, null, userdata);
|
||||
@@ -1918,29 +1947,6 @@ class WebGPUInterface {
|
||||
device.pushErrorScope(this.enums.ErrorFilter[filterInt]);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {number} deviceIdx
|
||||
* @param {number} callbackPtr
|
||||
* @param {number} userdata
|
||||
*/
|
||||
wgpuDeviceSetUncapturedErrorCallback: (deviceIdx, callbackPtr, userdata) => {
|
||||
const device = this.devices.get(deviceIdx);
|
||||
const callback = this.mem.exports.__indirect_function_table.get(callbackPtr);
|
||||
|
||||
device.onuncapturederror = (ev) => {
|
||||
console.warn(ev.error);
|
||||
let status = 4;
|
||||
if (error instanceof GPUValidationError) {
|
||||
status = 1;
|
||||
} else if (error instanceof GPUOutOfMemoryError) {
|
||||
status = 2;
|
||||
} else if (error instanceof GPUInternalError) {
|
||||
status = 3;
|
||||
}
|
||||
callback(status, null, userdata);
|
||||
};
|
||||
},
|
||||
|
||||
...this.devices.interface(true),
|
||||
|
||||
/* ---------------------- Instance ---------------------- */
|
||||
@@ -2646,23 +2652,23 @@ class WebGPUInterface {
|
||||
const formatStr = navigator.gpu.getPreferredCanvasFormat();
|
||||
const format = this.enums.TextureFormat.indexOf(formatStr);
|
||||
|
||||
this.mem.storeUint(capabilitiesPtr + this.mem.intSize, 1);
|
||||
this.mem.storeUint(capabilitiesPtr + 8, 1);
|
||||
const formatAddr = this.mem.exports.wgpu_alloc(4);
|
||||
this.mem.storeI32(formatAddr, format);
|
||||
this.mem.storeI32(capabilitiesPtr + this.mem.intSize*2, formatAddr);
|
||||
this.mem.storeI32(capabilitiesPtr + 8 + this.mem.intSize, formatAddr);
|
||||
|
||||
// NOTE: present modes don't seem to actually do anything in JS, we can just give back a default FIFO though.
|
||||
this.mem.storeUint(capabilitiesPtr + this.mem.intSize*3, 1);
|
||||
this.mem.storeUint(capabilitiesPtr + 8 + this.mem.intSize*2, 1);
|
||||
const presentModesAddr = this.mem.exports.wgpu_alloc(4);
|
||||
this.mem.storeI32(presentModesAddr, 0);
|
||||
this.mem.storeI32(capabilitiesPtr + this.mem.intSize*4, presentModesAddr);
|
||||
this.mem.storeI32(capabilitiesPtr + 8 + this.mem.intSize*3, presentModesAddr);
|
||||
|
||||
// Browser seems to support opaque (1) and premultiplied (2).
|
||||
this.mem.storeUint(capabilitiesPtr + this.mem.intSize*5, 2);
|
||||
this.mem.storeUint(capabilitiesPtr + 8 + this.mem.intSize*4, 2);
|
||||
const alphaModesAddr = this.mem.exports.wgpu_alloc(8);
|
||||
this.mem.storeI32(alphaModesAddr + 0, 1); // Opaque.
|
||||
this.mem.storeI32(alphaModesAddr + 4, 2); // premultiplied.
|
||||
this.mem.storeI32(capabilitiesPtr + this.mem.intSize*6, alphaModesAddr);
|
||||
this.mem.storeI32(capabilitiesPtr + 8 + this.mem.intSize*5, alphaModesAddr);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -2680,17 +2686,6 @@ class WebGPUInterface {
|
||||
// TODO: determine suboptimal and/or status.
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {number} surfaceIdx
|
||||
* @param {number} texturePtr
|
||||
* @returns {number}
|
||||
*/
|
||||
wgpuSurfaceGetPreferredFormat: (surfaceIdx, adapterIdx) => {
|
||||
const formatStr = navigator.gpu.getPreferredCanvasFormat();
|
||||
const format = this.enums.TextureFormat.indexOf(formatStr);
|
||||
return format;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {number} surfaceIdx
|
||||
*/
|
||||
|
||||
Vendored
+113
-53
@@ -13,7 +13,7 @@ when ODIN_OS == .Windows {
|
||||
@(private) LIB :: "lib/wgpu-windows-" + ARCH + "-" + TYPE + "/wgpu_native" + EXT
|
||||
|
||||
when !#exists(LIB) {
|
||||
#panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v0.19.4.1, make sure to read the README at '" + #directory + "vendor/wgpu/README.md'")
|
||||
#panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v22.1.0.1, make sure to read the README at '" + #directory + "README.md'")
|
||||
}
|
||||
|
||||
foreign import libwgpu {
|
||||
@@ -27,6 +27,8 @@ when ODIN_OS == .Windows {
|
||||
"system:advapi32.lib",
|
||||
"system:user32.lib",
|
||||
"system:gdi32.lib",
|
||||
"system:ole32.lib",
|
||||
"system:oleaut32.lib",
|
||||
}
|
||||
} else when ODIN_OS == .Darwin {
|
||||
@(private) ARCH :: "x86_64" when ODIN_ARCH == .amd64 else "aarch64" when ODIN_ARCH == .arm64 else #panic("unsupported WGPU Native architecture")
|
||||
@@ -34,7 +36,7 @@ when ODIN_OS == .Windows {
|
||||
@(private) LIB :: "lib/wgpu-macos-" + ARCH + "-" + TYPE + "/libwgpu_native" + EXT
|
||||
|
||||
when !#exists(LIB) {
|
||||
#panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v0.19.4.1, make sure to read the README at '" + #directory + "vendor/wgpu/README.md'")
|
||||
#panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v22.1.0.1, make sure to read the README at '" + #directory + "README.md'")
|
||||
}
|
||||
|
||||
foreign import libwgpu {
|
||||
@@ -49,7 +51,7 @@ when ODIN_OS == .Windows {
|
||||
@(private) LIB :: "lib/wgpu-linux-" + ARCH + "-" + TYPE + "/libwgpu_native" + EXT
|
||||
|
||||
when !#exists(LIB) {
|
||||
#panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v0.19.4.1, make sure to read the README at '" + #directory + "vendor/wgpu/README.md'")
|
||||
#panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v22.1.0.1, make sure to read the README at '" + #directory + "README.md'")
|
||||
}
|
||||
|
||||
foreign import libwgpu {
|
||||
@@ -220,7 +222,8 @@ CullMode :: enum i32 {
|
||||
|
||||
DeviceLostReason :: enum i32 {
|
||||
Undefined = 0x00000000,
|
||||
Destroyed = 0x00000001,
|
||||
Unknown = 0x00000001,
|
||||
Destroyed = 0x00000002,
|
||||
}
|
||||
|
||||
ErrorFilter :: enum i32 {
|
||||
@@ -264,6 +267,30 @@ FeatureName :: enum i32 {
|
||||
PipelineStatisticsQuery,
|
||||
StorageResourceBindingArray,
|
||||
PartiallyBoundBindingArray,
|
||||
TextureFormat16bitNorm,
|
||||
TextureCompressionAstcHdr,
|
||||
// TODO: requires wgpu.h api change
|
||||
// TimestampQueryInsidePasses,
|
||||
MappablePrimaryBuffers = 0x0003000E,
|
||||
BufferBindingArray,
|
||||
UniformBufferAndStorageTextureArrayNonUniformIndexing,
|
||||
// TODO: requires wgpu.h api change
|
||||
// AddressModeClampToZero,
|
||||
// AddressModeClampToBorder,
|
||||
// PolygonModeLine,
|
||||
// PolygonModePoint,
|
||||
// ConservativeRasterization,
|
||||
// ClearTexture,
|
||||
// SprivShaderPassThrough,
|
||||
// MultiView,
|
||||
VertexAttribute64bit = 0x00030019,
|
||||
TextureFormatNv12,
|
||||
RayTracingAccelarationStructure,
|
||||
RayQuery,
|
||||
ShaderF64,
|
||||
ShaderI16,
|
||||
ShaderPrimitiveIndex,
|
||||
ShaderEarlyDepthTest,
|
||||
}
|
||||
|
||||
FilterMode :: enum i32 {
|
||||
@@ -520,6 +547,18 @@ TextureFormat :: enum i32 {
|
||||
ASTC12x10UnormSrgb = 0x0000005D,
|
||||
ASTC12x12Unorm = 0x0000005E,
|
||||
ASTC12x12UnormSrgb = 0x0000005F,
|
||||
|
||||
// Native.
|
||||
|
||||
// From FeatureName.TextureFormat16bitNorm
|
||||
R16Unorm = 0x00030001,
|
||||
R16Snorm,
|
||||
Rg16Unorm,
|
||||
Rg16Snorm,
|
||||
Rgba16Unorm,
|
||||
Rgba16Snorm,
|
||||
// From FeatureName.TextureFormatNv12
|
||||
NV12,
|
||||
}
|
||||
|
||||
TextureSampleType :: enum i32 {
|
||||
@@ -581,13 +620,13 @@ VertexStepMode :: enum i32 {
|
||||
VertexBufferNotUsed = 0x00000002,
|
||||
}
|
||||
|
||||
// WGSLFeatureName :: enum i32 {
|
||||
// Undefined = 0x00000000,
|
||||
// ReadonlyAndReadwriteStorageTextures = 0x00000001,
|
||||
// Packed4x8IntegerDotProduct = 0x00000002,
|
||||
// UnrestrictedPointerParameters = 0x00000003,
|
||||
// PointerCompositeAccess = 0x00000004,
|
||||
// }
|
||||
WGSLFeatureName :: enum i32 {
|
||||
Undefined = 0x00000000,
|
||||
ReadonlyAndReadwriteStorageTextures = 0x00000001,
|
||||
Packed4x8IntegerDotProduct = 0x00000002,
|
||||
UnrestrictedPointerParameters = 0x00000003,
|
||||
PointerCompositeAccess = 0x00000004,
|
||||
}
|
||||
|
||||
BufferUsage :: enum i32 {
|
||||
MapRead = 0x00000000,
|
||||
@@ -634,22 +673,18 @@ TextureUsage :: enum i32 {
|
||||
}
|
||||
TextureUsageFlags :: bit_set[TextureUsage; Flags]
|
||||
|
||||
|
||||
BufferMapAsyncCallback :: #type proc "c" (status: BufferMapAsyncStatus, /* NULLABLE */ userdata: rawptr)
|
||||
ShaderModuleGetCompilationInfoCallback :: #type proc "c" (status: CompilationInfoRequestStatus, compilationInfo: ^CompilationInfo, /* NULLABLE */ userdata: rawptr)
|
||||
DeviceCreateComputePipelineAsyncCallback :: #type proc "c" (status: CreatePipelineAsyncStatus, pipeline: ComputePipeline, message: cstring, /* NULLABLE */ userdata: rawptr)
|
||||
DeviceCreateRenderPipelineAsyncCallback :: #type proc "c" (status: CreatePipelineAsyncStatus, pipeline: RenderPipeline, message: cstring, /* NULLABLE */ userdata: rawptr)
|
||||
Proc :: distinct rawptr
|
||||
|
||||
DeviceLostCallback :: #type proc "c" (reason: DeviceLostReason, message: cstring, userdata: rawptr)
|
||||
ErrorCallback :: #type proc "c" (type: ErrorType, message: cstring, userdata: rawptr)
|
||||
|
||||
Proc :: distinct rawptr
|
||||
|
||||
QueueOnSubmittedWorkDoneCallback :: #type proc "c" (status: QueueWorkDoneStatus, /* NULLABLE */ userdata: rawptr)
|
||||
InstanceRequestAdapterCallback :: #type proc "c" (status: RequestAdapterStatus, adapter: Adapter, message: cstring, /* NULLABLE */ userdata: rawptr)
|
||||
AdapterRequestDeviceCallback :: #type proc "c" (status: RequestDeviceStatus, device: Device, message: cstring, /* NULLABLE */ userdata: rawptr)
|
||||
|
||||
// AdapterRequestAdapterInfoCallback :: #type proc "c" (adapterInfo: AdapterInfo, /* NULLABLE */ userdata: rawptr)
|
||||
BufferMapAsyncCallback :: #type proc "c" (status: BufferMapAsyncStatus, /* NULLABLE */ userdata: rawptr)
|
||||
DeviceCreateComputePipelineAsyncCallback :: #type proc "c" (status: CreatePipelineAsyncStatus, pipeline: ComputePipeline, message: cstring, /* NULLABLE */ userdata: rawptr)
|
||||
DeviceCreateRenderPipelineAsyncCallback :: #type proc "c" (status: CreatePipelineAsyncStatus, pipeline: RenderPipeline, message: cstring, /* NULLABLE */ userdata: rawptr)
|
||||
InstanceRequestAdapterCallback :: #type proc "c" (status: RequestAdapterStatus, adapter: Adapter, message: cstring, /* NULLABLE */ userdata: rawptr)
|
||||
QueueOnSubmittedWorkDoneCallback :: #type proc "c" (status: QueueWorkDoneStatus, /* NULLABLE */ userdata: rawptr)
|
||||
ShaderModuleGetCompilationInfoCallback :: #type proc "c" (status: CompilationInfoRequestStatus, compilationInfo: ^CompilationInfo, /* NULLABLE */ userdata: rawptr)
|
||||
|
||||
ChainedStruct :: struct {
|
||||
next: ^ChainedStruct,
|
||||
@@ -661,28 +696,23 @@ ChainedStructOut :: struct {
|
||||
sType: SType,
|
||||
}
|
||||
|
||||
// AdapterInfo :: struct {
|
||||
// next: ^ChainedStructOut,
|
||||
// vendor: cstring,
|
||||
// architecture: cstring,
|
||||
// device: cstring,
|
||||
// description: cstring,
|
||||
// backendType: BackendType,
|
||||
// adapterType: AdapterType,
|
||||
// vendorID: u32,
|
||||
// deviceID: u32,
|
||||
// }
|
||||
|
||||
AdapterProperties :: struct {
|
||||
AdapterInfo :: struct {
|
||||
nextInChain: ^ChainedStructOut,
|
||||
vendorID: u32,
|
||||
vendorName: cstring,
|
||||
vendor: cstring,
|
||||
architecture: cstring,
|
||||
deviceID: u32,
|
||||
name: cstring,
|
||||
driverDescription: cstring,
|
||||
adapterType: AdapterType,
|
||||
device: cstring,
|
||||
description: cstring,
|
||||
backendType: BackendType,
|
||||
adapterType: AdapterType,
|
||||
vendorID: u32,
|
||||
deviceID: u32,
|
||||
}
|
||||
when ODIN_OS == .JS {
|
||||
#assert(int(BackendType.WebGPU) == 2)
|
||||
#assert(offset_of(AdapterInfo, backendType) == 20)
|
||||
|
||||
#assert(int(AdapterType.Unknown) == 3)
|
||||
#assert(offset_of(AdapterInfo, adapterType) == 24)
|
||||
}
|
||||
|
||||
BindGroupEntry :: struct {
|
||||
@@ -943,6 +973,7 @@ StorageTextureBindingLayout :: struct {
|
||||
|
||||
SurfaceCapabilities :: struct {
|
||||
nextInChain: ^ChainedStructOut,
|
||||
usages: TextureUsageFlags,
|
||||
formatCount: uint,
|
||||
formats: /* const */ [^]TextureFormat `fmt:"v,formatCount"`,
|
||||
presentModeCount: uint,
|
||||
@@ -950,6 +981,16 @@ SurfaceCapabilities :: struct {
|
||||
alphaModeCount: uint,
|
||||
alphaModes: /* const */ [^]CompositeAlphaMode `fmt:"v,alphaModeCount"`,
|
||||
}
|
||||
when ODIN_OS == .JS {
|
||||
#assert(offset_of(SurfaceCapabilities, formatCount) == 8)
|
||||
#assert(offset_of(SurfaceCapabilities, formats) == 8 + 1*size_of(int))
|
||||
|
||||
#assert(offset_of(SurfaceCapabilities, presentModeCount) == 8 + 2*size_of(int))
|
||||
#assert(offset_of(SurfaceCapabilities, presentModes) == 8 + 3*size_of(int))
|
||||
|
||||
#assert(offset_of(SurfaceCapabilities, alphaModeCount) == 8 + 4*size_of(int))
|
||||
#assert(offset_of(SurfaceCapabilities, alphaModes) == 8 + 5*size_of(int))
|
||||
}
|
||||
|
||||
SurfaceConfiguration :: struct {
|
||||
nextInChain: ^ChainedStruct,
|
||||
@@ -1040,6 +1081,12 @@ TextureViewDescriptor :: struct {
|
||||
aspect: TextureAspect,
|
||||
}
|
||||
|
||||
UncapturedErrorCallbackInfo :: struct {
|
||||
nextInChain: ^ChainedStruct,
|
||||
callback: ErrorCallback,
|
||||
userdata: rawptr,
|
||||
}
|
||||
|
||||
VertexAttribute :: struct {
|
||||
format: VertexFormat,
|
||||
offset: u64,
|
||||
@@ -1120,12 +1167,21 @@ ProgrammableStageDescriptor :: struct {
|
||||
RenderPassColorAttachment :: struct {
|
||||
nextInChain: ^ChainedStruct,
|
||||
/* NULLABLE */ view: TextureView,
|
||||
// depthSlice: u32,
|
||||
depthSlice: u32,
|
||||
/* NULLABLE */ resolveTarget: TextureView,
|
||||
loadOp: LoadOp,
|
||||
storeOp: StoreOp,
|
||||
clearValue: Color,
|
||||
}
|
||||
when ODIN_OS == .JS {
|
||||
#assert(size_of(RenderPassColorAttachment) == 56)
|
||||
#assert(offset_of(RenderPassColorAttachment, view) == 4)
|
||||
#assert(offset_of(RenderPassColorAttachment, depthSlice) == 8)
|
||||
#assert(offset_of(RenderPassColorAttachment, resolveTarget) == 12)
|
||||
#assert(offset_of(RenderPassColorAttachment, loadOp) == 16)
|
||||
#assert(offset_of(RenderPassColorAttachment, storeOp) == 20)
|
||||
#assert(offset_of(RenderPassColorAttachment, clearValue) == 24)
|
||||
}
|
||||
|
||||
RequiredLimits :: struct {
|
||||
nextInChain: ^ChainedStruct,
|
||||
@@ -1194,6 +1250,10 @@ DeviceDescriptor :: struct {
|
||||
defaultQueue: QueueDescriptor,
|
||||
deviceLostCallback: DeviceLostCallback,
|
||||
deviceLostUserdata: rawptr,
|
||||
uncapturedErrorCallbackInfo: UncapturedErrorCallbackInfo,
|
||||
}
|
||||
when ODIN_OS == .JS {
|
||||
#assert(offset_of(DeviceDescriptor, deviceLostCallback) == 24 + size_of(int))
|
||||
}
|
||||
|
||||
RenderPassDescriptor :: struct {
|
||||
@@ -1245,16 +1305,18 @@ foreign libwgpu {
|
||||
// Methods of Adapter
|
||||
@(link_name="wgpuAdapterEnumerateFeatures")
|
||||
RawAdapterEnumerateFeatures :: proc(adapter: Adapter, features: [^]FeatureName) -> uint ---
|
||||
@(link_name="wgpuAdapterGetInfo")
|
||||
RawAdapterGetInfo :: proc(adapter: Adapter, info: ^AdapterInfo) ---
|
||||
@(link_name="wgpuAdapterGetLimits")
|
||||
RawAdapterGetLimits :: proc(adapter: Adapter, limits: ^SupportedLimits) -> b32 ---
|
||||
@(link_name="wgpuAdapterGetProperties")
|
||||
RawAdapterGetProperties :: proc(adapter: Adapter, properties: ^AdapterProperties) ---
|
||||
AdapterHasFeature :: proc(adapter: Adapter, feature: FeatureName) -> b32 ---
|
||||
// AdapterRequestAdapterInfo :: proc(adapter: Adapter, callback: AdapterRequestAdapterInfoCallback, /* NULLABLE */ userdata: rawptr) ---
|
||||
AdapterRequestDevice :: proc(adapter: Adapter, /* NULLABLE */ descriptor: /* const */ ^DeviceDescriptor, callback: AdapterRequestDeviceCallback, /* NULLABLE */ userdata: rawptr = nil) ---
|
||||
AdapterReference :: proc(adapter: Adapter) ---
|
||||
AdapterRelease :: proc(adapter: Adapter) ---
|
||||
|
||||
// Procs of AdapterInfo
|
||||
AdapterInfoFreeMembers :: proc(adapterInfo: AdapterInfo) ---
|
||||
|
||||
// Methods of BindGroup
|
||||
BindGroupSetLabel :: proc(bindGroup: BindGroup, label: cstring) ---
|
||||
BindGroupReference :: proc(bindGroup: BindGroup) ---
|
||||
@@ -1348,13 +1410,12 @@ foreign libwgpu {
|
||||
DevicePopErrorScope :: proc(device: Device, callback: ErrorCallback, userdata: rawptr) ---
|
||||
DevicePushErrorScope :: proc(device: Device, filter: ErrorFilter) ---
|
||||
DeviceSetLabel :: proc(device: Device, label: cstring) ---
|
||||
DeviceSetUncapturedErrorCallback :: proc(device: Device, callback: ErrorCallback, userdata: rawptr) ---
|
||||
DeviceReference :: proc(device: Device) ---
|
||||
DeviceRelease :: proc(device: Device) ---
|
||||
|
||||
// Methods of Instance
|
||||
InstanceCreateSurface :: proc(instance: Instance, descriptor: /* const */ ^SurfaceDescriptor) -> Surface ---
|
||||
// InstanceHasWGSLLanguageFeature :: proc(instance: Instance, feature: WGSLFeatureName) -> b32 ---
|
||||
InstanceHasWGSLLanguageFeature :: proc(instance: Instance, feature: WGSLFeatureName) -> b32 ---
|
||||
InstanceProcessEvents :: proc(instance: Instance) ---
|
||||
InstanceRequestAdapter :: proc(instance: Instance, /* NULLABLE */ options: /* const */ ^RequestAdapterOptions, callback: InstanceRequestAdapterCallback, /* NULLABLE */ userdata: rawptr = nil) ---
|
||||
InstanceReference :: proc(instance: Instance) ---
|
||||
@@ -1455,9 +1516,8 @@ foreign libwgpu {
|
||||
RawSurfaceGetCapabilities :: proc(surface: Surface, adapter: Adapter, capabilities: ^SurfaceCapabilities) ---
|
||||
@(link_name="wgpuSurfaceGetCurrentTexture")
|
||||
RawSurfaceGetCurrentTexture :: proc(surface: Surface, surfaceTexture: ^SurfaceTexture) ---
|
||||
SurfaceGetPreferredFormat :: proc(surface: Surface, adapter: Adapter) -> TextureFormat ---
|
||||
SurfacePresent :: proc(surface: Surface) ---
|
||||
// SurfaceSetLabel :: proc(surface: Surface, label: cstring) ---
|
||||
SurfaceSetLabel :: proc(surface: Surface, label: cstring) ---
|
||||
SurfaceUnconfigure :: proc(surface: Surface) ---
|
||||
SurfaceReference :: proc(surface: Surface) ---
|
||||
SurfaceRelease :: proc(surface: Surface) ---
|
||||
@@ -1500,8 +1560,8 @@ AdapterGetLimits :: proc(adapter: Adapter) -> (limits: SupportedLimits, ok: bool
|
||||
return
|
||||
}
|
||||
|
||||
AdapterGetProperties :: proc(adapter: Adapter) -> (properties: AdapterProperties) {
|
||||
RawAdapterGetProperties(adapter, &properties)
|
||||
AdapterGetInfo :: proc(adapter: Adapter) -> (info: AdapterInfo) {
|
||||
RawAdapterGetInfo(adapter, &info)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1634,8 +1694,8 @@ SurfaceGetCurrentTexture :: proc(surface: Surface) -> (surface_texture: SurfaceT
|
||||
|
||||
// WGPU Native bindings
|
||||
|
||||
BINDINGS_VERSION :: [4]u8{0, 19, 4, 1}
|
||||
BINDINGS_VERSION_STRING :: "0.19.4.1"
|
||||
BINDINGS_VERSION :: [4]u8{22, 1, 0, 1}
|
||||
BINDINGS_VERSION_STRING :: "22.1.0.1"
|
||||
|
||||
when ODIN_OS != .JS {
|
||||
@(private="file", init)
|
||||
|
||||
Vendored
+5
@@ -72,6 +72,11 @@ XkbAllEventsMask :: XkbEventMask {
|
||||
.ExtensionDeviceNotify,
|
||||
}
|
||||
|
||||
/* ---- X11/extensions/XI2.h ---------------------------------------------------------*/
|
||||
|
||||
XIAllDevices :: 0
|
||||
XIAllMasterDevices :: 1
|
||||
|
||||
|
||||
/* ---- X11/Xlib.h ---------------------------------------------------------*/
|
||||
|
||||
|
||||
Vendored
+1675
-1675
File diff suppressed because it is too large
Load Diff
Vendored
+41
-5
@@ -9,13 +9,49 @@ foreign xlib {
|
||||
foreign import xcursor "system:Xcursor"
|
||||
@(default_calling_convention="c", link_prefix="X")
|
||||
foreign xcursor {
|
||||
cursorGetTheme :: proc(display: ^Display) -> cstring ---
|
||||
cursorGetDefaultSize :: proc(display: ^Display) -> i32 ---
|
||||
cursorLibraryLoadImage :: proc(name: cstring, theme: cstring, size: i32) -> rawptr ---
|
||||
cursorImageLoadCursor :: proc(display: ^Display, img: rawptr) -> Cursor ---
|
||||
cursorImageDestroy :: proc(img: rawptr) ---
|
||||
cursorGetTheme :: proc(display: ^Display) -> cstring ---
|
||||
cursorGetDefaultSize :: proc(display: ^Display) -> i32 ---
|
||||
cursorLibraryLoadCursor :: proc(display: ^Display, name: cstring) -> Cursor ---
|
||||
cursorLibraryLoadImage :: proc(name: cstring, theme: cstring, size: i32) -> rawptr ---
|
||||
cursorImageLoadCursor :: proc(display: ^Display, img: rawptr) -> Cursor ---
|
||||
cursorImageDestroy :: proc(img: rawptr) ---
|
||||
}
|
||||
|
||||
foreign import xfixes "system:Xfixes"
|
||||
@(default_calling_convention="c", link_prefix="XFixes")
|
||||
foreign xfixes {
|
||||
HideCursor :: proc(display: ^Display, window: Window) ---
|
||||
ShowCursor :: proc(display: ^Display, window: Window) ---
|
||||
}
|
||||
|
||||
foreign import xrandr "system:Xrandr"
|
||||
@(default_calling_convention="c")
|
||||
foreign xrandr {
|
||||
XRRSizes :: proc(display: ^Display, screen: i32, nsizes: ^i32) -> [^]XRRScreenSize ---
|
||||
XRRGetScreenResources :: proc(display: ^Display, window: Window) -> ^XRRScreenResources ---
|
||||
XRRFreeScreenResources :: proc(resources: ^XRRScreenResources) ---
|
||||
XRRGetOutputInfo :: proc(display: ^Display, resources: ^XRRScreenResources, output: RROutput) -> ^XRROutputInfo ---
|
||||
XRRFreeOutputInfo :: proc(output_info: ^XRROutputInfo) ---
|
||||
XRRGetCrtcInfo :: proc(display: ^Display, resources: ^XRRScreenResources, crtc: RRCrtc) -> ^XRRCrtcInfo ---
|
||||
XRRFreeCrtcInfo :: proc(crtc_info: ^XRRCrtcInfo) ---
|
||||
XRRGetMonitors :: proc(dpy: ^Display, window: Window, get_active: b32, nmonitors: ^i32) -> [^]XRRMonitorInfo ---
|
||||
}
|
||||
|
||||
foreign import xinput "system:Xi"
|
||||
foreign xinput {
|
||||
XISelectEvents :: proc(display: ^Display, window: Window, masks: [^]XIEventMask, num_masks: i32) -> i32 ---
|
||||
XIQueryVersion :: proc(display: ^Display, major: ^i32, minor: ^i32) -> Status ---
|
||||
}
|
||||
|
||||
XISetMask :: proc(ptr: [^]u8, event: XIEventType) {
|
||||
ptr[cast(i32)event >> 3] |= (1 << cast(uint)((cast(i32)event) & 7))
|
||||
}
|
||||
|
||||
XIMaskIsSet :: proc(ptr: [^]u8, event: i32) -> bool {
|
||||
return (ptr[event >> 3] & (1 << cast(uint)((event) & 7))) != 0
|
||||
}
|
||||
|
||||
|
||||
/* ---- X11/Xlib.h ---------------------------------------------------------*/
|
||||
|
||||
@(default_calling_convention="c", link_prefix="X")
|
||||
|
||||
Vendored
+499
-311
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user