diff --git a/Shared/Bridge/FEngine.h b/Shared/Bridge/FEngine.h index 3d2cd83..105cded 100644 --- a/Shared/Bridge/FEngine.h +++ b/Shared/Bridge/FEngine.h @@ -40,6 +40,8 @@ typedef NS_ENUM(NSInteger, Direction){ @property (nonatomic, strong, readonly) NSArray* _Nonnull games; @property (nonatomic, assign) NSUInteger currentGameIndex; +@property (nonatomic, assign) NSUInteger currentMoveNodeUUID; + - (id _Nonnull)init; - (BOOL)loadOpening:(NSString* _Nonnull)pgn; @@ -56,7 +58,6 @@ typedef NS_ENUM(NSInteger, Direction){ - (NSString* _Nonnull)PGNFormattedForDisplay; - (NSArray* _Nonnull)moveNodesTree; -- (NSUInteger)currentMoveNodeUUID; - (NSArray* _Nonnull)allMoves; - (NSArray* _Nonnull)movesAt:(NSUInteger)rank file:(NSUInteger)file; diff --git a/Shared/Bridge/FEngine.mm b/Shared/Bridge/FEngine.mm index 52c657a..69af909 100644 --- a/Shared/Bridge/FEngine.mm +++ b/Shared/Bridge/FEngine.mm @@ -37,6 +37,7 @@ @implementation FEngine @synthesize games; @synthesize currentGameIndex; +@synthesize currentMoveNodeUUID; + (void)initialize { if (self == [FEngine class]) { @@ -160,6 +161,10 @@ - (void)moveNodesFromNode:(ChessGame::MoveNode)node return rootNode.variations; } +- (void)setCurrentMoveNodeUUID:(NSUInteger)currentMoveNodeUUID { + engine.game().setCurrentMoveUUID((unsigned int)currentMoveNodeUUID); +} + - (NSUInteger)currentMoveNodeUUID { return engine.game().getCurrentMoveUUID(); } diff --git a/Shared/ChessDocument.swift b/Shared/ChessDocument.swift index 18720c8..c5e1161 100644 --- a/Shared/ChessDocument.swift +++ b/Shared/ChessDocument.swift @@ -81,6 +81,14 @@ struct ChessDocument: FileDocument { } } + var currentMoveIndex: UInt = 0 { + didSet { + engine.currentMoveNodeUUID = currentMoveIndex + selection = Selection.empty() + variations.show = false + } + } + var whitePlayer: GamePlayer var blackPlayer: GamePlayer diff --git a/Shared/Engine/Engine/ChessGame.cpp b/Shared/Engine/Engine/ChessGame.cpp index f417d85..6249073 100644 --- a/Shared/Engine/Engine/ChessGame.cpp +++ b/Shared/Engine/Engine/ChessGame.cpp @@ -55,7 +55,7 @@ std::vector ChessGame::movesAt(File file, Rank rank) { std::vector ChessGame::allMoves() { std::vector all; MoveNode currentNode = root; - root.visit(0, moveIndexes, [&all](auto & node) { + root.visit(0, moveIndexes, moveIndexes.moveCursor, [&all](auto & node, int cursor) { all.push_back(node.move); }); return all; diff --git a/Shared/Engine/Engine/ChessGame.hpp b/Shared/Engine/Engine/ChessGame.hpp index 3a74b45..2992991 100644 --- a/Shared/Engine/Engine/ChessGame.hpp +++ b/Shared/Engine/Engine/ChessGame.hpp @@ -80,6 +80,7 @@ class ChessGame { std::vector variations; typedef std::function NodeCallback; + typedef std::function NodeCallback2; // Find the node that represents the move at `atIndex`. Note that `atIndex==0` represents // the "root" node, which is not a move. The first move is actually at `atIndex==1`. @@ -94,11 +95,13 @@ class ChessGame { } } - void visit(int cursor, MoveIndexes indexes, NodeCallback callback) { - if (cursor < indexes.moveCursor) { + void visit(int cursor, MoveIndexes indexes, int untilCursorIndex, NodeCallback2 callback) { + if (cursor < untilCursorIndex) { int varIndex = indexes.moves[cursor]; - callback(variations[varIndex]); - variations[varIndex].visit(cursor+1, indexes, callback); + assert(varIndex < variations.size()); + // TODO: revisit the cursor+1 which is needed because the root node is at cursor==0 + callback(variations[varIndex], cursor+1); + variations[varIndex].visit(cursor+1, indexes, untilCursorIndex, callback); } } @@ -174,6 +177,14 @@ class ChessGame { return uuid; } + void setCurrentMoveUUID(unsigned int uuid) { + root.visit(0, moveIndexes, (int)moveIndexes.moves.size(), [this, &uuid](auto & node, auto cursor) { + if (node.uuid == uuid) { + moveIndexes.moveCursor = cursor; + } + }); + } + MoveNode getRoot() { return root; } diff --git a/Shared/Views/ContentView.swift b/Shared/Views/ContentView.swift index 1fc558d..abba323 100644 --- a/Shared/Views/ContentView.swift +++ b/Shared/Views/ContentView.swift @@ -40,7 +40,7 @@ struct ContentView: View { if (showInfo) { VStack(alignment: .leading, spacing: 10) { NavigationView(document: $document) - InformationView(document: document) + InformationView(document: $document) } .frame(minWidth: 350, idealWidth: 350, maxWidth: 350, alignment: .leading) } diff --git a/Shared/Views/InformationView.swift b/Shared/Views/InformationView.swift index 9497c6d..a458f52 100644 --- a/Shared/Views/InformationView.swift +++ b/Shared/Views/InformationView.swift @@ -10,13 +10,13 @@ import SwiftUI struct InformationView: View { - let document: ChessDocument + @Binding var document: ChessDocument let numberFormatter = NumberFormatter() let valueFormatter = NumberFormatter() - init(document: ChessDocument) { - self.document = document + init(document: Binding) { + self._document = document numberFormatter.numberStyle = .decimal numberFormatter.groupingSeparator = "," @@ -75,7 +75,10 @@ struct InformationView: View { } List(document.game.moves, children: \FullMove.children) { item in - FullMoveView(item: item, currentMoveUUID: document.engine.currentMoveNodeUUID()) + FullMoveView(item: item, currentMoveUUID: document.engine.currentMoveNodeUUID) + .onTapGesture { + document.currentMoveIndex = UInt(item.id)! + } } Spacer() @@ -98,11 +101,11 @@ struct BottomInformationView_Previews: PreviewProvider { static var previews: some View { Group { let doc = ChessDocument(pgn: "1. e4 e5 *") - InformationView(document: doc) + InformationView(document: .constant(doc)) } Group { let doc = ChessDocument(pgn: "1. e4 e5 2. Nf3 Nf6 3. Nxe5 d6 4. Nc3 dxe5 *") - InformationView(document: doc) + InformationView(document: .constant(doc)) } } }