Skip to content

Commit

Permalink
ADD getScores (domain approach)
Browse files Browse the repository at this point in the history
  • Loading branch information
ninovanhooff committed Oct 24, 2024
1 parent 3d85dc8 commit e8f2304
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 17 deletions.
14 changes: 8 additions & 6 deletions src/playdate/bindings/scoreboards.nim
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ type PDScoresListRaw* {.importc: "PDScoresList", header: "pd_api.h", bycopy.} =
boardID* {.importc: "boardID".}: cstring
count* {.importc: "count".}: cuint
lastUpdated* {.importc: "lastUpdated".}: cuint
playerIncluded* {.importc: "playerIncluded".}: cint
playerIncluded* {.importc: "playerIncluded".}: cuint
limit* {.importc: "limit".}: cuint
scores* {.importc: "scores".}: ptr PDScoreRaw

type PDScoresListPtr* = ptr PDScoresListRaw

type PDBoardRaw* {.importc: "PDBoard", header: "pd_api.h", bycopy.} = object
boardID* {.importc: "boardID".}: cstring
name* {.importc: "name".}: cstring
Expand All @@ -30,7 +32,7 @@ type PDBoardsListRaw* {.importc: "PDBoardsList", header: "pd_api.h", bycopy.} =
type PersonalBestCallbackRaw* {.importc: "PersonalBestCallback", header: "pd_api.h".} = proc (score: PDScorePtr; errorMessage: cstring) {.cdecl.}
type AddScoreCallbackRaw* {.importc: "AddScoreCallback", header: "pd_api.h".} = proc (score: PDScorePtr; errorMessage: cstring) {.cdecl.}
# type BoardsListCallbackRaw* = proc (boards: ptr PDBoardsListRaw; errorMessage: cstring) {.cdecl.}
# type ScoresCallbackRaw* = proc (scores: ptr PDScoresListRaw; errorMessage: cstring) {.cdecl.}
type ScoresCallbackRaw* = proc (scores: ptr PDScoresListRaw; errorMessage: cstring) {.cdecl.}

sdktype:
type PlaydateScoreboards* {.importc: "const struct playdate_scoreboards", header: "pd_api.h".} = object
Expand All @@ -43,7 +45,7 @@ sdktype:
# callback: BoardsListCallbackRaw): cint {.cdecl.}
# freeBoardsList* {.importc: "freeBoardsList".}: proc (
# boardsList: ptr PDBoardsList) {.cdecl.}
# getScores* {.importc: "getScores".}: proc (boardId: cstring;
# callback: ScoresCallbackRaw): cint {.cdecl.}
# freeScoresList* {.importc: "freeScoresList".}: proc (
# scoresList: ptr PDScoresList) {.cdecl.}
getScoresBinding* {.importc: "getScores".}: proc (boardId: cstring;
callback: ScoresCallbackRaw): cint {.cdecl, raises: [].}
freeScoresList* {.importc: "freeScoresList".}: proc (
scoresList: PDScoresListPtr) {.cdecl, raises: [].}
69 changes: 58 additions & 11 deletions src/playdate/scoreboards.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import std/importutils

import system
import types {.all.}
import bindings/[api, types]
import bindings/scoreboards

Expand All @@ -25,40 +25,86 @@ type PDScore* = object of RootObj
rank*: uint32
player*: string

type PDScoresList* = object of RootObj
boardID*: string
lastUpdated*: uint32
scores*: seq[PDScore]
# these properties are not implemented yet in the Playdate API
# playerIncluded*: uint32
# limit*: uint32

type
PersonalBestCallback* = proc(score: PDScore, errorMessage: string)
AddScoreCallback* = proc(score: PDScore, errorMessage: string)
# BoardsListCallback* = proc(boards: ptr PDBoardsList, errorMessage: string)
# ScoresCallback* = proc(scores: ptr PDScoresList, errorMessage: string)
ScoresCallback* = proc(scores: PDScoresList, errorMessage: string)

var privatePersonalBestCallback: PersonalBestCallback
var privatePersonalBestCallbacks = newSeq[PersonalBestCallback]()
var privateAddScoreCallback: AddScoreCallback
var privateScoresCallbacks = newSeq[ScoresCallback]()

proc newPDScoresList(boardID: string, lastUpdated: uint32, scores: seq[PDScore]): PDScoresList =
result.boardID = boardID
result.lastUpdated = lastUpdated
result.scores = scores

proc invokePersonalBestCallback(score: PDScorePtr, errorMessage: ConstChar) {.cdecl, raises: [].} =
if errorMessage != nil:
privatePersonalBestCallback(PDScore(value: 0, rank: 0, player: ""), $errorMessage)
let callback = privatePersonalBestCallbacks.pop() # first in, first out
if score == nil and errorMessage == nil:
callback(PDScore(), "Playdate-nim: No personal best")
return

if score == nil:
privatePersonalBestCallback(PDScore(), "Playdate-nim: No personal best")
callback(PDScore(), $errorMessage)
return

let domainScore = PDScore(value: score.value.uint32, rank: score.rank.uint32, player: $score.player)
playdate.scoreboards.freeScore(score)
privatePersonalBestCallback(domainScore, $errorMessage)
callback(domainScore, $errorMessage)

proc invokeAddScoreCallback(score: PDScorePtr, errorMessage: ConstChar) {.cdecl, raises: [].} =
if errorMessage != nil:
privateAddScoreCallback(PDScore(value: 0, rank: 0, player: ""), $errorMessage)
return

# todo create newPDSCore constructor
let domainScore = PDScore(value: score.value.uint32, rank: score.rank.uint32, player: $score.player)
playdate.scoreboards.freeScore(score)
privateAddScoreCallback(domainScore, $errorMessage)

proc invokeScoresCallback(scoresList: PDScoresListPtr, errorMessage: ConstChar) {.cdecl, raises: [].} =
privateAccess(PlaydateScoreboards)
let callback = privateScoresCallbacks.pop() # first in, first out
if scoresList == nil and errorMessage == nil:
let domainObject = newPDScoresList(boardID = "", lastUpdated = 0, scores = @[])
callback(domainObject, "Playdate-nim: No scores")
return

if scoresList == nil:
let domainObject = newPDScoresList(boardID = "", lastUpdated = 0, scores = @[])
callback(domainObject, $errorMessage)
return

privateAccess(SDKArray)
let length = scoresList.count.cint
let cArray = SDKArray[PDScoreRaw](data: cast[ptr UncheckedArray[PDScoreRaw]](scoresList.scores), len: length)

var scoresSeq = newSeq[PDScore](length)
for i in 0 ..< length:
let score = cArray[i]
scoresSeq[i] = PDScore(value: score.value.uint32, rank: score.rank.uint32, player: $score.player)

# todo enabling this cleanup code freezes the simulator. Should we free individual scores? With or without: both freeze
# for i in 0 ..< length:
# playdate.scoreboards.freeScore(addr cArray[i])
# playdate.scoreboards.freeScoresList(scoresList)

let domainObject = newPDScoresList(boardID = $scoresList.boardID, lastUpdated = scoresList.lastUpdated, scores = scoresSeq)
callback(domainObject, $errorMessage)

proc getPersonalBest*(this: ptr PlaydateScoreboards, boardID: string, callback: PersonalBestCallback): int32 =
privateAccess(PlaydateScoreboards)
privatePersonalBestCallback = callback
privatePersonalBestCallbacks.insert(callback)
return this.getPersonalBestBinding(boardID.cstring, invokePersonalBestCallback)

proc addScore*(this: ptr PlaydateScoreboards, boardID: string, value: uint32, callback: AddScoreCallback): int32 =
Expand All @@ -69,6 +115,7 @@ proc addScore*(this: ptr PlaydateScoreboards, boardID: string, value: uint32, ca
# proc getScoreboards*(this: ptr PlaydateScoreboards, callback: BoardsListCallback): int32 =
# privateAccess(PlaydateScoreboards)
# # proc freeBoardsList*(boardsList: ptr PDBoardsList)
# proc getScores*(this: ptr PlaydateScoreboards, boardID: string, callback: ScoresCallback): int32 =
# privateAccess(PlaydateScoreboards)
# # proc freeScoresList*(scoresList: ptr PDScoresList)
proc getScores*(this: ptr PlaydateScoreboards, boardID: string, callback: ScoresCallback): int32 =
privateAccess(PlaydateScoreboards)
privateScoresCallbacks.insert(callback)
return this.getScoresBinding(boardID.cstring, invokeScoresCallback)

0 comments on commit e8f2304

Please sign in to comment.