Converted get/set methods pairs to computed properties throughout the Playdate bindings target.

This commit is contained in:
2026-07-26 00:20:19 +02:00
parent 8b002d9be8
commit 2b046005d1
8 changed files with 36 additions and 47 deletions
@@ -32,7 +32,7 @@ final class Game {
private let boxSize = 24
func start() {
Display.setRefreshRate(50)
Display.refreshRate = 50
System.addMenuItem(title: "reset") { _ in
Game.shared.reset()
+2 -1
View File
@@ -103,7 +103,7 @@ final class Game {
var player = Sprite()
func start() {
Display.setRefreshRate(50)
Display.refreshRate = 50
System.setUpdateCallback {
self.update()
@@ -300,6 +300,7 @@ try Lua.addFunction(double, name: "mylib.double")
## Conventions
- **Namespaces.** The subsystem namespaces (`System`, `Graphics`, `Sound`, …) live at the top level of the module; only the raw C API bootstrap stays under `Playdate` (`Playdate.initialize(with:)`, `Playdate.api`). On a name collision with another module, qualify with the module name: `PlaydateKit.System`.
- **Properties vs. methods.** State the OS can report back is a property: read-write where the C API has a get/set pair (`Display.refreshRate`, `Source.volume`), get-only where it only has a getter (`Display.fps`). A `set…` method means the C API is write-only there (`Display.setScale`, `Synth.setAttackTime`) or setting takes extra arguments — a property getter never invents a value the OS can't return. Callbacks are installed with `set…Callback`/`set…Function` methods.
- **Errors.** Fallible operations use typed throws — `throws(PlaydateError)` generally, `throws(Network.NetError)` for network I/O — so `catch` gives you a concrete type, and no `any Error` existentials are needed.
- **Ownership.** A wrapper that *creates* a C object frees it on `deinit`; keep the wrapper referenced for as long as you use it. Wrappers vending OS-owned objects (a `Bitmap` from a `BitmapTable`, a track from a `Sequence`, …) don't free them — keep the owner alive instead, as documented on each API. Resources a C object keeps referencing (a sprite's image, a synth's sample, modulators, menu-item option titles) are retained by the wrapper automatically.
- **Callbacks.** Where the C API provides a userdata slot, closures are supported everywhere and delivered back with the right wrapper. A few C callbacks have no userdata (serial messages, headphone changes, scoreboard
+4 -6
View File
@@ -13,15 +13,13 @@ extension Display {
/// The display height in pixels, taking the current scale into account.
public static var height: Int { Int(api.pointee.getHeight.unsafelyUnwrapped()) }
/// Sets the nominal refresh rate in frames per second. Pass 0 to update
/// The nominal refresh rate in frames per second. Set to 0 to update
/// as fast as possible (the update callback drives the pace).
public static func setRefreshRate(_ rate: Float) {
api.pointee.setRefreshRate.unsafelyUnwrapped(rate)
public static var refreshRate: Float {
get { api.pointee.getRefreshRate.unsafelyUnwrapped() }
set { api.pointee.setRefreshRate.unsafelyUnwrapped(newValue) }
}
/// The current nominal refresh rate.
public static var refreshRate: Float { api.pointee.getRefreshRate.unsafelyUnwrapped() }
/// The measured average frames per second.
public static var fps: Float { api.pointee.getFPS.unsafelyUnwrapped() }
+2 -6
View File
@@ -211,13 +211,9 @@ extension Graphics {
}
/// Extra space added between letters, in pixels.
public static func setTextTracking(_ tracking: Int) {
gfx.pointee.setTextTracking.unsafelyUnwrapped(Int32(tracking))
}
/// The extra space currently added between letters, in pixels.
public static var textTracking: Int {
Int(gfx.pointee.getTextTracking.unsafelyUnwrapped())
get { Int(gfx.pointee.getTextTracking.unsafelyUnwrapped()) }
set { gfx.pointee.setTextTracking.unsafelyUnwrapped(Int32(newValue)) }
}
/// Adjusts the line height used when drawing multi-line text.
@@ -31,7 +31,7 @@ final class Game {
nonisolated(unsafe) static let shared = Game()
func start() {
Display.setRefreshRate(50)
Display.refreshRate = 50
System.setUpdateCallback {
self.update()
+10 -12
View File
@@ -119,13 +119,12 @@ extension Sound {
}
/// Modulates the channel's volume.
public func setVolumeModulator(_ modulator: SignalValue?) {
retain(modulator)
Channel.api.pointee.setVolumeModulator.unsafelyUnwrapped(pointer, modulator?.pointer)
}
public var volumeModulator: SignalValue? {
SignalValue.wrap(Channel.api.pointee.getVolumeModulator.unsafelyUnwrapped(pointer))
get { SignalValue.wrap(Channel.api.pointee.getVolumeModulator.unsafelyUnwrapped(pointer)) }
set {
retain(newValue)
Channel.api.pointee.setVolumeModulator.unsafelyUnwrapped(pointer, newValue?.pointer)
}
}
/// The channel's stereo pan: -1 (left) to 1 (right).
@@ -135,13 +134,12 @@ extension Sound {
/// Modulates the channel's pan. The signal's range 0...1 maps to
/// left...right.
public func setPanModulator(_ modulator: SignalValue?) {
retain(modulator)
Channel.api.pointee.setPanModulator.unsafelyUnwrapped(pointer, modulator?.pointer)
}
public var panModulator: SignalValue? {
SignalValue.wrap(Channel.api.pointee.getPanModulator.unsafelyUnwrapped(pointer))
get { SignalValue.wrap(Channel.api.pointee.getPanModulator.unsafelyUnwrapped(pointer)) }
set {
retain(newValue)
Channel.api.pointee.setPanModulator.unsafelyUnwrapped(pointer, newValue?.pointer)
}
}
/// A signal following the channel's dry (unprocessed) level.
@@ -16,21 +16,19 @@ extension Sound {
self.isOwned = isOwned
}
/// Sets the playback volume for the left and right channels, 0...1.
public func setVolume(left: Float, right: Float) {
Source.api.pointee.setVolume.unsafelyUnwrapped(pointer, left, right)
/// The playback volume of the left and right channels, 0...1.
public var volume: (left: Float, right: Float) {
get {
var left: Float = 0, right: Float = 0
Source.api.pointee.getVolume.unsafelyUnwrapped(pointer, &left, &right)
return (left, right)
}
set { Source.api.pointee.setVolume.unsafelyUnwrapped(pointer, newValue.left, newValue.right) }
}
/// Sets the playback volume of both channels.
public func setVolume(_ volume: Float) {
setVolume(left: volume, right: volume)
}
/// The playback volume of the left and right channels.
public var volume: (left: Float, right: Float) {
var left: Float = 0, right: Float = 0
Source.api.pointee.getVolume.unsafelyUnwrapped(pointer, &left, &right)
return (left, right)
self.volume = (volume, volume)
}
public var isPlaying: Bool {
@@ -93,16 +93,14 @@ extension Sound {
Instrument.api.pointee.allNotesOff.unsafelyUnwrapped(pointer, when)
}
/// Sets the volume of the left and right channels, 0...1.
public func setVolume(left: Float, right: Float) {
Instrument.api.pointee.setVolume.unsafelyUnwrapped(pointer, left, right)
}
/// The volume of the left and right channels.
/// The volume of the left and right channels, 0...1.
public var volume: (left: Float, right: Float) {
var left: Float = 0, right: Float = 0
Instrument.api.pointee.getVolume.unsafelyUnwrapped(pointer, &left, &right)
return (left, right)
get {
var left: Float = 0, right: Float = 0
Instrument.api.pointee.getVolume.unsafelyUnwrapped(pointer, &left, &right)
return (left, right)
}
set { Instrument.api.pointee.setVolume.unsafelyUnwrapped(pointer, newValue.left, newValue.right) }
}
/// The number of voices currently playing.