Skip to content

Commit

Permalink
✨ (UIExplorer): Add Xylophone musical instrument activity
Browse files Browse the repository at this point in the history
- add MIDI files to Utils
- remove old Xylophone and MIDI system
- add Instrument and Xylophone views
- start to deprecate old system Melody with changes
  • Loading branch information
HPezz authored and ladislas committed Nov 29, 2023
1 parent d15a425 commit 55ba4bc
Show file tree
Hide file tree
Showing 20 changed files with 312 additions and 165 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Leka - iOS Monorepo
# Copyright 2023 APF France handicap
# SPDX-License-Identifier: Apache-2.0

id: cd5d93afbd8f4071b25479cd6372a7a9
name: Xylophone Heptatonic
description: L'objectif est de jouer de la musique à l'aide du xylophone
image: activity_color_recognition_1
sequence:
- exercises:
- instructions: Joue du xylophone avec Leka
interface: musicalInstruments
payload:
instrument: xylophone
scale: majorHeptatonic
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Leka - iOS Monorepo
# Copyright 2023 APF France handicap
# SPDX-License-Identifier: Apache-2.0

id: 264d720bf8904043b97d5d7b3d0e7124
name: Xylophone Pentatonic
description: L'objectif est de jouer de la musique à l'aide du xylophone
image: activity_color_recognition_1
sequence:
- exercises:
- instructions: Joue du xylophone avec Leka
interface: musicalInstruments
payload:
instrument: xylophone
scale: majorPentatonic
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ let kActivities: [Activity] = [
ContentKit.decodeActivity("remote-standard"),
ContentKit.decodeActivity("remote-arrow"),
ContentKit.decodeActivity("activity-hideAndSeek"),
ContentKit.decodeActivity("activity-xylophone-pentatonic"),
ContentKit.decodeActivity("activity-xylophone-heptatonic"),
]

struct GEKNewSystemView: View {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Leka - iOS Monorepo
// Copyright 2023 APF France handicap
// SPDX-License-Identifier: Apache-2.0

public enum MusicalInstrument {

public struct Payload: Codable {
public let instrument: String
public let scale: String

enum CodingKeys: String, CodingKey {

Check failure on line 11 in Modules/ContentKit/Sources/Exercise/Exercice+MusicalInstrument.swift

View workflow job for this annotation

GitHub Actions / lint

Types should be nested at most 1 level deep (nesting)

Check failure on line 11 in Modules/ContentKit/Sources/Exercise/Exercice+MusicalInstrument.swift

View workflow job for this annotation

GitHub Actions / lint

Types should be nested at most 1 level deep (nesting)
case instrument, scale
}

public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)

self.instrument = try container.decode(String.self, forKey: .instrument)
self.scale = try container.decode(String.self, forKey: .scale)
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ extension Exercise {
case remoteStandard
case remoteArrow
case hideAndSeek
case musicalInstruments
}

}
1 change: 1 addition & 0 deletions Modules/ContentKit/Sources/Exercise/Exercise+Payload.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ extension DragAndDropIntoZones.Payload: ExercisePayloadProtocol {}
extension DragAndDropToAssociate.Payload: ExercisePayloadProtocol {}
extension AudioRecordingPlayer.Payload: ExercisePayloadProtocol {}
extension HideAndSeek.Payload: ExercisePayloadProtocol {}
extension MusicalInstrument.Payload: ExercisePayloadProtocol {}
3 changes: 3 additions & 0 deletions Modules/ContentKit/Sources/Exercise/Exercise.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ public struct Exercise: Codable {
case (.hideAndSeek, .none):
payload = try container.decode(HideAndSeek.Payload.self, forKey: .payload)

case (.musicalInstruments, .none):
payload = try container.decode(MusicalInstrument.Payload.self, forKey: .payload)

case (.remoteStandard, .none),
(.remoteArrow, .none):
payload = nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@

import AudioKit
import Combine
import ContentKit
import SwiftUI

public class MelodyGameplay: ObservableObject {
@Published public var progress: CGFloat = 0.0
@Published var state: ExerciseState = .idle

private let xyloPlayer = MIDIPlayer(name: "Xylophone", samples: xyloSamples)
private let xyloPlayer = MIDIPlayer(instrument: .xylophone)

private let song: MelodySongModel

Expand Down Expand Up @@ -68,6 +69,6 @@ public class MelodyGameplay: ObservableObject {
let index = kListOfTiles.firstIndex(where: {
$0.noteNumber == currentNoteNumber
})
return kListOfTiles[index!].color
return kListOfTiles[index!].color.screen
}
}
17 changes: 13 additions & 4 deletions Modules/GameEngineKit/Sources/Staging/Melody/MelodyView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,16 @@
// Copyright 2023 APF France handicap
// SPDX-License-Identifier: Apache-2.0

import DesignKit
import AudioKit
import RobotKit
import SwiftUI

public struct XylophoneTile: Identifiable {
public var id: Int
var noteNumber: MIDINoteNumber
var color: Robot.Color
}

public let kListOfTiles: [XylophoneTile] = [
XylophoneTile(id: 0, noteNumber: 24, color: .pink),
XylophoneTile(id: 1, noteNumber: 26, color: .red),
Expand All @@ -19,7 +26,7 @@ public struct MelodyView: View {
@ObservedObject private var viewModel: MelodyViewModel

let defaultTilesSpacing: CGFloat = 16
let tilesNumber = 7
let tileNumber = 7

public init(gameplay: MelodyGameplay) {
self.viewModel = MelodyViewModel(gameplay: gameplay)
Expand All @@ -36,9 +43,11 @@ public struct MelodyView: View {
Button {
viewModel.onTileTapped(tile: tile)
} label: {
tile.color
tile.color.screen
}
.buttonStyle(XylophoneTileButtonStyle(index: tile.id, tilesNumber: tilesNumber))
.buttonStyle(
MusicalInstrumentView.XylophoneView.TileButtonStyle(index: tile.id, tileNumber: tileNumber)
)
.compositingGroup()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class MelodyViewModel: Identifiable, ObservableObject {
public var gameplay: MelodyGameplay

@Published public var progress: CGFloat
@Published var state: ExerciseState
@Published var state: ExerciseState

private var cancellables: Set<AnyCancellable> = []

Expand Down

This file was deleted.

80 changes: 0 additions & 80 deletions Modules/GameEngineKit/Sources/Staging/XylophoneTile.swift

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Leka - iOS Monorepo
// Copyright 2023 APF France handicap
// SPDX-License-Identifier: Apache-2.0

import AudioKit
import DesignKit
import RobotKit
import SwiftUI

extension MusicalInstrumentView.XylophoneView {

struct TileButtonStyle: ButtonStyle {
let xyloAttachColor = Color(red: 0.87, green: 0.65, blue: 0.54)
let defaultMaxTileHeight: Int = 500
let defaultTileHeightGap: Int = 250
let defaultTileWidth: CGFloat = 130
let defaultTilesScaleFeedback: CGFloat = 0.98
let defaultTilesRotationFeedback: CGFloat = -1

let index: Int
let tileNumber: Int

func makeBody(configuration: Self.Configuration) -> some View {
configuration.label
.overlay {
VStack {
Spacer()
Circle()
.fill(xyloAttachColor)
.shadow(
color: .black.opacity(0.4),
radius: 3, x: 0, y: 3
)
Spacer()
Circle()
.fill(xyloAttachColor)
.shadow(
color: .black.opacity(0.4),
radius: 3, x: 0, y: 3
)
Spacer()
}
.frame(width: 44)
}
.overlay {
RoundedRectangle(cornerRadius: 7, style: .circular)
.stroke(.black.opacity(configuration.isPressed ? 0.3 : 0), lineWidth: 20)
}
.clipShape(RoundedRectangle(cornerRadius: 7, style: .circular))
.frame(width: defaultTileWidth, height: setSizeFromIndex())
.scaleEffect(
configuration.isPressed ? defaultTilesScaleFeedback : 1,
anchor: .center
)
.rotationEffect(
Angle(degrees: configuration.isPressed ? defaultTilesRotationFeedback : 0),
anchor: .center
)
.shadow(
color: .black.opacity(0.4),
radius: 3, x: 0, y: 3
)
}

private func setSizeFromIndex() -> CGFloat {
let sizeDiff = defaultTileHeightGap / tileNumber
let tileHeight = defaultMaxTileHeight - index * sizeDiff

return CGFloat(tileHeight)
}
}

}

#Preview {
Button {
// Nothing to do
} label: {
Color(.red)
}
.buttonStyle(MusicalInstrumentView.XylophoneView.TileButtonStyle(index: 0, tileNumber: 1))
}
Loading

0 comments on commit 55ba4bc

Please sign in to comment.