diff --git a/.gitignore b/.gitignore
index 777f0de0c75a8..cc06ef55f0ad4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -216,6 +216,7 @@ stage
# Apple Xcode IDE
Xcode/
+*.xcodeproj
# gdb
.gdb_history
@@ -245,5 +246,8 @@ weather.output
.jekyll-metadata
Gemfile.lock
+# xcodegen developer id file
+xcode_dev_id.yml
+
# VERSION.txt generated by our CMakeLists.txt
VERSION.txt
diff --git a/build-data/ios/resources/AppIcon.icns b/build-data/ios/resources/AppIcon.icns
new file mode 100644
index 0000000000000..d5bf44f64ab97
Binary files /dev/null and b/build-data/ios/resources/AppIcon.icns differ
diff --git a/build-data/ios/resources/LaunchScreen.png b/build-data/ios/resources/LaunchScreen.png
new file mode 100644
index 0000000000000..260cfcc104ea4
Binary files /dev/null and b/build-data/ios/resources/LaunchScreen.png differ
diff --git a/build-data/ios/resources/LaunchScreen.storyboard b/build-data/ios/resources/LaunchScreen.storyboard
new file mode 100644
index 0000000000000..dd2564863a477
--- /dev/null
+++ b/build-data/ios/resources/LaunchScreen.storyboard
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build-scripts/ios-xcode.sh b/build-scripts/ios-xcode.sh
new file mode 100644
index 0000000000000..ced330ae73d28
--- /dev/null
+++ b/build-scripts/ios-xcode.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+# adapted from https://marcelbraghetto.github.io/a-simple-triangle/
+
+# Given the name of a Homebrew formula, check if its installed and if not, install it.
+fetch_brew_dependency() {
+ FORMULA_NAME=$1
+
+ echo "Checking for Brew dependency: '$FORMULA_NAME'."
+
+ if brew ls --versions $FORMULA_NAME > /dev/null; then
+ echo "Dependency '$FORMULA_NAME' is already installed, continuing ..."
+ else
+ echo "Dependency '$FORMULA_NAME' is not installed, installing via Homebrew ..."
+ brew install $FORMULA_NAME
+ fi
+}
+
+fetch_brew_dependency "xcodegen"
+
+echo "Checking for build folder ..."
+if [ ! -d "../build" ]; then
+ mkdir ../build
+fi
+
+echo "Checking for libs folder ..."
+if [ ! -d "../build/libs" ]; then
+ echo "ERROR: Static SDL libraries not found at /build/libs ..."
+ echo "Reffer to /doc/COMPILING/COMPILING-XCODE.md for instructions on how to build the static libraries."
+ exit
+fi
+
+
+if [ ! -f "xcode_dev_id.yml" ]; then
+ echo "xcode_dev_id.yml not found -"
+ echo " You will need to manually specify your Development Team for signing in Xcode."
+ echo " See the following link for details:"
+ echo " https://help.apple.com/xcode/mac/current/#/dev23aab79b4"
+ echo ""
+ echo "To avoid this message in the future see the xcode_dev_id_example.yml file."
+fi
+# Invoke the xcodegen tool to create our project file.
+echo "Generating Xcode project"
+xcodegen -s xcodegen-cataclysm.yml -p ../build
+
+if [ ! -f "../build/CataclysmExperimental.xcodeproj" ]; then
+ echo "Project built successfully. Launching Xcode..."
+ open ../build/CataclysmExperimental.xcodeproj
+ exit
+else
+ echo "Error in project creation process. Review output above for errors."
+fi
\ No newline at end of file
diff --git a/build-scripts/xcode_dev_id_example.yml b/build-scripts/xcode_dev_id_example.yml
new file mode 100644
index 0000000000000..898f9ad733578
--- /dev/null
+++ b/build-scripts/xcode_dev_id_example.yml
@@ -0,0 +1,5 @@
+# For more information on setting up a development team see:
+# https://help.apple.com/developer-account/#/devf2eb157f8
+
+settings:
+ DEVELOPMENT_TEAM: XXXXXXXXXX
\ No newline at end of file
diff --git a/build-scripts/xcodegen-cataclysm.yml b/build-scripts/xcodegen-cataclysm.yml
new file mode 100644
index 0000000000000..f3316b0160ea2
--- /dev/null
+++ b/build-scripts/xcodegen-cataclysm.yml
@@ -0,0 +1,149 @@
+name: CataclysmExperimental
+
+include:
+ # see xcode_dev_id_example.yml
+ - xcode_dev_id.yml
+
+options:
+ bundleIdPrefix: com.cataclysmdda.en.cataclysm
+ groupOrdering:
+ - order: [Sources, Resources, Frameworks, Products]
+ usesTabs: false
+ indentWidth: 4
+ tabWidth: 4
+ deploymentTarget:
+ iOS: "15.0"
+
+schemes:
+ CataclysmExperimental:
+ build:
+ targets:
+ CataclysmExperimental: all
+
+targets:
+ CataclysmExperimental:
+ type: application
+ platform: iOS
+ info:
+ path: ../build/Info.plist
+ properties:
+ LSRequiresIPhoneOS: true
+ UIRequiredDeviceCapabilities: [arm64]
+ UIRequiresFullScreen: true
+ UIStatusBarHidden: true
+ UISupportedInterfaceOrientations:
+ - UIInterfaceOrientationLandscapeLeft
+ - UIInterfaceOrientationLandscapeRight
+ UILaunchStoryboardName: LaunchScreen
+ CFBundleIconFile: AppIcon.icns
+ UIApplicationSupportsIndirectInputEvents: true
+ UIFileSharingEnabled: true
+ LSSupportsOpeningDocumentsInPlace: true
+ sources:
+ - path: ../src
+ name: Sources
+ buildPhase: sources
+ includes:
+ - "**/swift/*.swift"
+ - "**/third-party/imgui/*.cpp"
+ - "**/third-party/imgui/*.h"
+ - "*.cpp"
+ - "*.h"
+ excludes:
+ - "*.txt"
+ - "*.in"
+ - "*.rc"
+ - "*.cmake"
+ - "**/third-party/flatbuffers/**"
+ - "**/third-party/ghc/**"
+ - "**/third-party/imtui/**"
+ - "**/third-party/pinyin/**"
+ - "**/chkjson/**"
+ - path: ../build-data/ios/resources/LaunchScreen.storyboard
+ group: Resources
+ - path: ../build-data/ios/resources/AppIcon.icns
+ group: Resources
+ buildPhase: resources
+ - path: ../build-data/ios/resources/LaunchScreen.png
+ group: Resources
+ buildPhase: resources
+ # TODO: Imitate cmake selection for data and gfx
+ - path: ../data
+ type: folder
+ group: Resources
+ buildPhase: resources
+ - path: ../gfx
+ type: folder
+ group: Resources
+ buildPhase: resources
+ - path: ../ios
+ type: folder
+ group: Resources
+ buildPhase: resources
+ settings:
+ base:
+ CLANG_CXX_LANGUAGE_STANDARD: c++17
+ CMAKE_CXX_STANDARD: 17
+ CMAKE_CXX_STANDARD_REQUIRED: ON
+ CMAKE_CXX_EXTENSIONS: OFF
+ CLANG_WARN_DOCUMENTATION_COMMENTS: false
+ CLANG_ENABLE_MODULES: YES
+ GCC_WARN_64_TO_32_BIT_CONVERSION: No
+ SWIFT_OBJC_INTEROP_MODE: objcxx
+ HEADER_SEARCH_PATHS:
+ - ../src/third-party/**
+ - ../build/libs/headers
+ LIBRARY_SEARCH_PATHS:
+ - ../build/libs/
+ - $(inherited)
+ GCC_PREPROCESSOR_DEFINITIONS:
+ - GIT_VERSION
+ - TILES
+ - BACKTRACE
+ - SDL_SOUND
+ - $(inherited)
+ OTHER_CPLUSPLUSFLAGS:
+ #- "-Werror"
+ - "-Wall -Wextra -Wformat-signedness -Wlogical-op -Wmissing-declarations -Wmissing-noreturn"
+ - "-Wnon-virtual-dtor -Wold-style-cast -Woverloaded-virtual -Wpedantic -Wsuggest-override"
+ - "-Wunused-macros -Wzero-as-null-pointer-constant -Wno-unknown-warning-option -Wno-nullability-extension -Wredundant-decls"
+ - "-fsigned-char"
+ OTHER_LDFLAGS:
+ - "-Wl,-ld_classic"
+ Debug:
+ OTHER_CPLUSPLUSFLAGS:
+ - "-Og -pthread '-std=c++17'"
+ Release:
+ GCC_PREPROCESSOR_DEFINITIONS:
+ - RELEASE
+ OTHER_CPLUSPLUSFLAGS:
+ - "-Os -DNDEBUG -pthread '-std=c++17'"
+ dependencies:
+ # TODO: build libcataclysm-tiles-common.a as it's own step again. Currently rolled in to single build
+ # - framework: libs/libcataclysm-tiles-common.a
+ - framework: ../build/libs/libSDL2.a
+ - framework: ../build/libs/libSDL2_image.a
+ - framework: ../build/libs/libSDL2_mixer.a
+ - framework: ../build/libs/libSDL2_ttf.a
+ - sdk: libllvm-flatbuffers.tbd
+ - sdk: libz.tbd
+ - sdk: libncurses.tbd
+ - sdk: MobileCoreServices.framework
+ - sdk: CoreMotion.framework
+ - sdk: CoreGraphics.framework
+ - sdk: CoreHaptics.framework
+ - sdk: AudioToolbox.framework
+ - sdk: CoreAudio.framework
+ - sdk: QuartzCore.framework
+ - sdk: GameController.framework
+ - sdk: Foundation.framework
+ - sdk: OpenGLES.framework
+ - sdk: UIKit.framework
+ - sdk: AVFoundation.framework
+ - sdk: ImageIO.framework
+ - sdk: Metal.framework
+ configs:
+ Debug:
+ DEBUG_MODE: YES
+ Release:
+ DEBUG_MODE: NO
diff --git a/data/json/construction/walls.json b/data/json/construction/walls.json
index a11c10c688abe..207c040aeb1e9 100644
--- a/data/json/construction/walls.json
+++ b/data/json/construction/walls.json
@@ -1408,4 +1408,4 @@
"pre_terrain": "t_wall_wood",
"post_terrain": "t_wood_wall_y"
}
-]
+]
\ No newline at end of file
diff --git a/doc/COMPILING_XCODE.md b/doc/COMPILING_XCODE.md
new file mode 100644
index 0000000000000..ee05dc512ae33
--- /dev/null
+++ b/doc/COMPILING_XCODE.md
@@ -0,0 +1,56 @@
+# Disclaimer
+
+**WARNING**: Xcode build should be used for _iOS builds only_. This can only be done on OS X.
+
+To build CataclysmDDA for other OS, see:
+
+- [COMPILING.md](COMPILING.md)
+
+# Prerequisites
+
+The project will build for tiles and sound by default.
+
+_Note: At this time there is no specific guidance on minimum versioning, all testing has been done on iOS 15.0+_
+
+### Get the tools
+
+- Xcode on the AppStore - https://apps.apple.com/us/app/xcode/id497799835.
+- Install Brew - https://brew.sh/
+ Or in a terminal window run:
+ `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"`
+
+### Build SDL libs for iOS
+
+You will need to download the SDL source code and build static libraries for iOS (ARM64). The source code is available [here](https://github.com/libsdl-org/SDL). Directions on building the SDL for iOS in Xcode is available [here](https://github.com/libsdl-org/SDL/blob/main/docs/README-ios.md). The project setup will expect to find the static libraries in `/build/libs` and related header files in `/build/libs/headers`.
+
+### (Optional) Apple Developer ID pre-configuration
+
+If you already know you developer ID, you can add it to the file `xcode_dev_id_example.yml`, and rename the file to `xcode_dev_id.yml`.
+
+Additional details are in the example file.
+
+### Run the script
+
+Open terminal window to the build-scripts directory and run:
+`./ios-xcode.sh`
+
+If the Xcode project builds successfully Xcode will try to open automatically.
+
+### Xcode Steps
+
+If you have not already set the developer ID you will need to set it in the Project settings in the section "Signing & Capabilities"
+
+Product->Run will build for debugging
+Product->Archive will build a release version.
+
+### Play!
+
+Configuration and save files are accessible in your documents folder via the Files app. This should allow you to import and export data from other places. For now there is no auto-synchronization with any cloud based data services.
+
+### Notes
+
+I appreciate the many folks in the community who have contributed to making such a wonderful game, and my intent was to make sure that everyone had access to an iPad version that was freely available and built to integrate with the existing codebase, making it inclusive of experimental builds.
+
+If there are other setup related steps needed, please update accordingly or find me on Discord with questions or issues (smileynet on both Official and Community servers) understanding that my support of this build is at-will and may be intermittent. (Written on 10/26/2022, if you are unable to @ me on either server, I have likely wandered on down the road or been ill prepared for an encounter with a Kevlar Hulk o.O)
+
+My use case for this build is playing on an iPad with an attached magic keyboard, so while I've tested the soft keyboard's basic functionality, at this point I have not done any of the UI enhancements found in the other ports found on the AppStore (or the Android build, but with any luck that will be reasonable to reuse in this case).
\ No newline at end of file
diff --git a/doc/EFFECT_ON_CONDITION.md b/doc/EFFECT_ON_CONDITION.md
index cf7b574706627..a798387d64b02 100644
--- a/doc/EFFECT_ON_CONDITION.md
+++ b/doc/EFFECT_ON_CONDITION.md
@@ -4731,4 +4731,4 @@ Combination of values work as `and`, no matter how they are arranged. This two n
```
```json
"search_data": [ { "category": "weapons", "wielded_only": true } ]
-```
+```
\ No newline at end of file
diff --git a/ios/joystick.png b/ios/joystick.png
new file mode 100644
index 0000000000000..eb0c0ac854f77
Binary files /dev/null and b/ios/joystick.png differ
diff --git a/src/activity_item_handling.cpp b/src/activity_item_handling.cpp
index f9d73d1d9fdde..f907efe3b7078 100644
--- a/src/activity_item_handling.cpp
+++ b/src/activity_item_handling.cpp
@@ -3717,4 +3717,4 @@ bool try_fuel_fire( player_activity &act, Character &you, const bool starting_fi
}
}
return true;
-}
+}
\ No newline at end of file
diff --git a/src/advanced_inv.cpp b/src/advanced_inv.cpp
index 24745dab3edfb..1d07454d49d36 100644
--- a/src/advanced_inv.cpp
+++ b/src/advanced_inv.cpp
@@ -68,7 +68,7 @@
#include "units_utility.h"
#include "vehicle.h"
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
# include
#endif
diff --git a/src/advanced_inv_pane.cpp b/src/advanced_inv_pane.cpp
index 792d9a7c9b315..fcb05faba226a 100644
--- a/src/advanced_inv_pane.cpp
+++ b/src/advanced_inv_pane.cpp
@@ -29,7 +29,7 @@
class item_category;
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
# include
#endif
diff --git a/src/bionics_ui.cpp b/src/bionics_ui.cpp
index 5dced78d52090..0de187004c3d8 100644
--- a/src/bionics_ui.cpp
+++ b/src/bionics_ui.cpp
@@ -757,7 +757,7 @@ void avatar::power_bionics()
scroll_position = clamp( scroll_position, 0, max_scroll_position );
cursor = clamp( cursor, 0, current_bionic_list->size() );
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
ctxt.get_registered_manual_keys().clear();
for( size_t i = 0; i < current_bionic_list->size(); i++ ) {
ctxt.register_manual_key( ( *current_bionic_list )[i]->invlet,
diff --git a/src/cata_tiles.cpp b/src/cata_tiles.cpp
index bc8290aa1edde..91995ffe2a978 100644
--- a/src/cata_tiles.cpp
+++ b/src/cata_tiles.cpp
@@ -1313,7 +1313,7 @@ void cata_tiles::draw( const point &dest, const tripoint ¢er, int width, int
return;
}
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
// Attempted bugfix for Google Play crash - prevent divide-by-zero if no tile
// width/height specified
if( tile_width == 0 || tile_height == 0 ) {
diff --git a/src/debug.cpp b/src/debug.cpp
index 469e8d56f5e0c..922e0cc417d01 100644
--- a/src/debug.cpp
+++ b/src/debug.cpp
@@ -1542,7 +1542,7 @@ std::string game_info::operating_system()
#if TARGET_IPHONE_SIMULATOR == 1
/* iOS in Xcode simulator */
return "iOS Simulator";
-#elif TARGET_OS_IPHONE == 1
+#elif TARGET_OS_IPHONE == 1 || defined(__IPHONEOS__)
/* iOS on iPhone, iPad, etc. */
return "iOS";
#elif TARGET_OS_MAC == 1
diff --git a/src/do_turn.cpp b/src/do_turn.cpp
index 12ec3c7a6e524..d2991472af22f 100644
--- a/src/do_turn.cpp
+++ b/src/do_turn.cpp
@@ -90,7 +90,7 @@ static const event_statistic_id event_statistic_last_words( "last_words" );
static const trait_id trait_HAS_NEMESIS( "HAS_NEMESIS" );
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
extern std::map> quick_shortcuts_map;
extern bool add_best_key_for_action_to_quick_shortcuts( action_id action,
const std::string &category, bool back );
@@ -217,7 +217,7 @@ bool cleanup_at_end()
MAPBUFFER.clear();
overmap_buffer.clear();
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
quick_shortcuts_map.clear();
#endif
return true;
diff --git a/src/emit.h b/src/emit.h
index bb1bdf00f937c..2c099b8504fdb 100644
--- a/src/emit.h
+++ b/src/emit.h
@@ -7,7 +7,7 @@
#include "field_type.h"
#include "type_id.h"
-#include
+#include "dialogue_helpers.h"
class JsonObject;
diff --git a/src/game.h b/src/game.h
index 12b8baff6853c..9952845da6b1b 100644
--- a/src/game.h
+++ b/src/game.h
@@ -849,7 +849,7 @@ class game
// Game-start procedures
bool load( const save_t &name ); // Load a player-specific save file
void load_master(); // Load the master data file, with factions &c
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
void load_shortcuts( const cata_path &path );
#endif
bool start_game(); // Starts a new game in the active world
@@ -861,7 +861,7 @@ class game
void serialize_master( std::ostream &fout );
// returns false if saving failed for whatever reason
bool save_maps();
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
void save_shortcuts( std::ostream &fout );
#endif
// Data Initialization
diff --git a/src/grab.cpp b/src/grab.cpp
index a6187040bb717..f7bce2c05fbb2 100644
--- a/src/grab.cpp
+++ b/src/grab.cpp
@@ -15,7 +15,7 @@
#include "vehicle.h"
#include "vpart_position.h"
#include "vpart_range.h"
-#include
+#include "veh_type.h"
bool game::grabbed_veh_move( const tripoint_rel_ms &dp )
{
diff --git a/src/handle_action.cpp b/src/handle_action.cpp
index 194dbadc6bb8e..fc18929b06bcd 100644
--- a/src/handle_action.cpp
+++ b/src/handle_action.cpp
@@ -176,7 +176,7 @@ static const zone_type_id zone_type_VEHICLE_REPAIR( "VEHICLE_REPAIR" );
#define dbg(x) DebugLog((x),D_GAME) << __FILE__ << ":" << __LINE__ << ": "
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
extern std::map> quick_shortcuts_map;
extern bool add_best_key_for_action_to_quick_shortcuts( action_id action,
const std::string &category, bool back );
@@ -3182,7 +3182,7 @@ bool game::handle_action()
if( act == ACTION_NULL ) {
return false;
}
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
if( get_option( "ANDROID_ACTIONMENU_AUTOADD" ) && ctxt.get_category() == "DEFAULTMODE" ) {
add_best_key_for_action_to_quick_shortcuts( act, ctxt.get_category(), false );
}
diff --git a/src/input.cpp b/src/input.cpp
index 8362bc90d5721..9e7026123ff9f 100644
--- a/src/input.cpp
+++ b/src/input.cpp
@@ -62,7 +62,7 @@ bool is_mouse_enabled()
bool is_keycode_mode_supported()
{
-#if defined(TILES) && !defined(__ANDROID__) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1)
+#if defined(TILES) && !defined(__ANDROID__) && !defined(__IPHONEOS__)
return keycode_mode;
#else
return false;
@@ -90,9 +90,7 @@ input_event::input_event( const std::set &mod, const int s, const inpu
: type( t ), modifiers( mod ), edit_refresh( false )
{
sequence.emplace_back( s );
-#if defined(__ANDROID__)
shortcut_last_used_action_counter = 0;
-#endif
}
int input_event::get_first_input() const
diff --git a/src/input_context.cpp b/src/input_context.cpp
index b0be192c505f2..c3d85718460ef 100644
--- a/src/input_context.cpp
+++ b/src/input_context.cpp
@@ -152,7 +152,6 @@ const std::string &input_context::input_to_action( const input_event &inp ) cons
return CATA_ERROR;
}
-#if defined(__ANDROID__)
std::list input_context::input_context_stack;
void input_context::register_manual_key( manual_key mk )
@@ -176,7 +175,6 @@ void input_context::register_manual_key( int key, const std::string text )
registered_manual_keys.push_back( manual_key( key, text ) );
}
-#endif
void input_context::register_action( const std::string &action_descriptor )
{
@@ -1510,4 +1508,4 @@ const hotkey_queue &hotkey_queue::alpha_digits()
queue->modifiers_keycode.emplace_back( std::set( { keymod_t::shift } ) );
}
return *queue;
-}
+}
\ No newline at end of file
diff --git a/src/input_context.h b/src/input_context.h
index 2520b1a47da1d..753f00d035dc2 100644
--- a/src/input_context.h
+++ b/src/input_context.h
@@ -8,9 +8,7 @@
#include
#include
-#if defined(__ANDROID__)
#include
-#endif
#include "action.h"
#include "input_enums.h"
@@ -40,17 +38,13 @@ class input_context
{
friend class keybindings_ui;
public:
-#if defined(__ANDROID__)
// Whatever's on top is our current input context.
static std::list input_context_stack;
-#endif
input_context() : registered_any_input( false ), category( "default" ),
coordinate_input_received( false ), handling_coordinate_input( false ) {
-#if defined(__ANDROID__)
input_context_stack.push_back( this );
allow_text_entry = false;
-#endif
register_action( "toggle_language_to_en" );
}
// TODO: consider making the curses WINDOW an argument to the constructor, so that mouse input
@@ -60,14 +54,11 @@ class input_context
: registered_any_input( false ), category( category ),
coordinate_input_received( false ), handling_coordinate_input( false ),
preferred_keyboard_mode( preferred_keyboard_mode ) {
-#if defined(__ANDROID__)
input_context_stack.push_back( this );
allow_text_entry = false;
-#endif
register_action( "toggle_language_to_en" );
}
-#if defined(__ANDROID__)
virtual ~input_context() {
input_context_stack.remove( this );
}
@@ -145,7 +136,6 @@ class input_context
bool operator!=( const input_context &other ) const {
return !( *this == other );
}
-#endif
/**
* Register an action with this input context.
@@ -415,9 +405,7 @@ class input_context
input_event first_unassigned_hotkey( const hotkey_queue &queue ) const;
input_event next_unassigned_hotkey( const hotkey_queue &queue, const input_event &prev ) const;
private:
-#if defined(__ANDROID__)
std::vector registered_manual_keys;
-#endif
std::vector registered_actions;
std::string edittext;
public:
diff --git a/src/input_enums.h b/src/input_enums.h
index 314a0cd676456..26c570bb2470c 100644
--- a/src/input_enums.h
+++ b/src/input_enums.h
@@ -78,10 +78,8 @@ struct input_event {
std::string edit;
bool edit_refresh;
-#if defined(__ANDROID__)
// Used exclusively by the quick shortcuts to determine how stale a shortcut is
int shortcut_last_used_action_counter = 0;
-#endif
input_event() : edit_refresh( false ) {
type = input_event_t::error;
@@ -164,4 +162,4 @@ enum class keyboard_mode {
// some platforms, such as non-android SDL. On other platforms
// this falls back to `keychar` automatically.
keycode,
-};
+};
\ No newline at end of file
diff --git a/src/inventory.cpp b/src/inventory.cpp
index 7dd4ddd1dfe3e..3368ac2e128ac 100644
--- a/src/inventory.cpp
+++ b/src/inventory.cpp
@@ -351,7 +351,7 @@ void inventory::push_back( const item &newit )
add_item( newit );
}
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
extern void remove_stale_inventory_quick_shortcuts();
#endif
@@ -446,7 +446,7 @@ void inventory::restack( Character &p )
}
items.sort( stack_compare );
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
remove_stale_inventory_quick_shortcuts();
#endif
}
diff --git a/src/inventory_ui.cpp b/src/inventory_ui.cpp
index 4cc044ada0691..0322708f433e4 100644
--- a/src/inventory_ui.cpp
+++ b/src/inventory_ui.cpp
@@ -1,4 +1,6 @@
+#if !defined(__IPHONEOS__)
#include "inventory_ui.h"
+#endif
#include
#include
@@ -50,7 +52,12 @@
#include "vehicle_selector.h"
#include "vpart_position.h"
-#if defined(__ANDROID__)
+#if defined(__IPHONEOS__)
+#include "inventory_ui.h"
+#include "input_context.h"
+#endif
+
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
#include
#endif
@@ -3842,7 +3849,8 @@ inventory_drop_selector::inventory_drop_selector( Character &p,
inventory_multiselector( p, preset, selection_column_title ),
warn_liquid( warn_liquid )
{
-#if defined(__ANDROID__)
+ //FIXME: allow_text_entry is inaccessible??????
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
// allow user to type a drop number without dismissing virtual keyboard after each keypress
ctxt.allow_text_entry = true;
#endif
@@ -3854,7 +3862,8 @@ inventory_insert_selector::inventory_insert_selector( Character &p,
const bool warn_liquid ) :
inventory_drop_selector( p, preset, selection_column_title, warn_liquid )
{
-#if defined(__ANDROID__)
+ //FIXME: allow_text_entry is inaccessible??????
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
// allow user to type a drop number without dismissing virtual keyboard after each keypress
ctxt.allow_text_entry = true;
#endif
@@ -4175,7 +4184,8 @@ pickup_selector::pickup_selector( Character &p, const inventory_selector_preset
{
ctxt.register_action( "WEAR" );
ctxt.register_action( "WIELD" );
-#if defined(__ANDROID__)
+ //FIXME: allow_text_entry is inaccessible??????
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
// allow user to type a drop number without dismissing virtual keyboard after each keypress
ctxt.allow_text_entry = true;
#endif
diff --git a/src/lang_stats.cpp b/src/lang_stats.cpp
index b5a29320d9df3..944bc6376ce62 100644
--- a/src/lang_stats.cpp
+++ b/src/lang_stats.cpp
@@ -1,10 +1,10 @@
#include
-#include
+#include "lang_stats.h"
using namespace std::literals::string_view_literals;
static constexpr std::initializer_list all_lang_stats = {
-#include
+#include "lang_stats.inc"
};
const lang_stats *lang_stats_for( std::string_view lang )
diff --git a/src/magic_enchantment.h b/src/magic_enchantment.h
index d3871fd062ee6..6a75df29fa29e 100644
--- a/src/magic_enchantment.h
+++ b/src/magic_enchantment.h
@@ -15,7 +15,7 @@
#include "magic.h"
#include "type_id.h"
#include "units_fwd.h"
-#include
+#include "monster.h"
class Character;
class Creature;
diff --git a/src/main.cpp b/src/main.cpp
index fb9dce428c37a..00a940c4cd294 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -83,12 +83,15 @@ class ui_adaptor;
# endif
#endif
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
+#include
#include
#include
-#include
-#include
#include
+#endif
+
+#if defined(__ANDROID__)
+#include
// Taken from: https://codelab.wordpress.com/2014/11/03/how-to-use-standard-output-streams-for-logging-in-android-apps/
// Force Android standard output to adb logcat output
@@ -622,7 +625,7 @@ int APIENTRY WinMain( _In_ HINSTANCE /* hInstance */, _In_opt_ HINSTANCE /* hPre
{
int argc = __argc;
char **argv = __argv;
-#elif defined(__ANDROID__)
+#elif defined(__ANDROID__) || defined(__IPHONEOS__)
extern "C" int SDL_main( int argc, char **argv ) {
#else
int main( int argc, const char *argv[] )
@@ -666,23 +669,20 @@ int main( int argc, const char *argv[] )
std::string external_storage_path( SDL_AndroidGetExternalStoragePath() );
PATH_INFO::init_base_path( external_storage_path );
-#else
- // Set default file paths
-#if defined(PREFIX)
+#elif defined(PREFIX)
PATH_INFO::init_base_path( std::string( PREFIX ) );
#else
PATH_INFO::init_base_path( "" );
#endif
-#endif
#if defined(__ANDROID__)
PATH_INFO::init_user_dir( external_storage_path );
-#else
-# if defined(USE_HOME_DIR) || defined(USE_XDG_DIR) || defined(EMSCRIPTEN)
+#elif defined(__IPHONEOS__)
+ PATH_INFO::init_user_dir( std::string( getenv( "HOME" ) ) + "/Documents/" );
+#elif defined(USE_HOME_DIR) || defined(USE_XDG_DIR) || defined(EMSCRIPTEN)
PATH_INFO::init_user_dir( "" );
-# else
+#else
PATH_INFO::init_user_dir( "." );
-# endif
#endif
PATH_INFO::set_standard_filenames();
@@ -869,3 +869,17 @@ int main( int argc, const char *argv[] )
exit_handler( -999 );
return 0;
}
+
+#if defined(__IPHONEOS__)
+#ifndef SDL_MAIN_HANDLED
+#include
+#ifdef main
+#undef main
+#endif
+
+int main( int argc, char *argv[] )
+{
+ return SDL_UIKitRunApp( argc, argv, SDL_main );
+}
+#endif /* !SDL_MAIN_HANDLED */
+#endif
diff --git a/src/messages.cpp b/src/messages.cpp
index 3fbbf8c623563..029cf64c479c3 100644
--- a/src/messages.cpp
+++ b/src/messages.cpp
@@ -19,7 +19,7 @@
#include "ui_manager.h"
#include "viewer.h"
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
#include
#endif
#include
diff --git a/src/mutation_ui.cpp b/src/mutation_ui.cpp
index 3502c5212404e..888bb5659c5d4 100644
--- a/src/mutation_ui.cpp
+++ b/src/mutation_ui.cpp
@@ -224,7 +224,7 @@ void avatar::power_mutations()
ctxt.register_action( "CONFIRM" );
ctxt.register_action( "HELP_KEYBINDINGS" );
ctxt.register_action( "QUIT" );
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
for( const auto &p : passive ) {
ctxt.register_manual_key( my_mutations[p].key, p.obj().name() );
}
diff --git a/src/npctalk.cpp b/src/npctalk.cpp
index b7a23d982f11c..4240187ba667e 100644
--- a/src/npctalk.cpp
+++ b/src/npctalk.cpp
@@ -2866,7 +2866,7 @@ talk_topic dialogue::opt( dialogue_window &d_win, const talk_topic &topic )
std::vector response_lines;
std::vector response_hotkeys;
const auto generate_response_lines = [&]() {
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
ctxt.get_registered_manual_keys().clear();
#endif
const hotkey_queue &queue = hotkey_queue::alphabets();
@@ -2877,7 +2877,7 @@ talk_topic dialogue::opt( dialogue_window &d_win, const talk_topic &topic )
const talk_data &td = response.create_option_line( *this, evt, d_win.is_computer );
response_lines.emplace_back( td );
response_hotkeys.emplace_back( evt );
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
ctxt.register_manual_key( evt.get_first_input(), td.text );
#endif
evt = ctxt.next_unassigned_hotkey( queue, evt );
diff --git a/src/npctalk_funcs.cpp b/src/npctalk_funcs.cpp
index 807fe415c6290..873d6578aa7d5 100644
--- a/src/npctalk_funcs.cpp
+++ b/src/npctalk_funcs.cpp
@@ -12,7 +12,7 @@
#include
#include "activity_actor_definitions.h"
-#include
+#include "activity_handlers.h"
#include "activity_type.h"
#include "auto_pickup.h"
#include "avatar.h"
diff --git a/src/options.cpp b/src/options.cpp
index 012932f23050b..5b00b3fc626b4 100644
--- a/src/options.cpp
+++ b/src/options.cpp
@@ -217,8 +217,8 @@ options_manager::options_manager()
pages_.emplace_back( "debug", to_translation( "Debug" ) );
}
-#if defined(__ANDROID__)
- pages_.emplace_back( "android", to_translation( "Android" ) );
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
+ pages_.emplace_back( "android", to_translation( "Mobile" ) );
#endif
enable_json( "DEFAULT_REGION" );
@@ -2621,7 +2621,7 @@ void options_manager::add_options_graphics()
display_list.front().first, COPT_CURSES_HIDE );
#endif
-#if !defined(__ANDROID__) || !defined(__EMSCRIPTEN__) // Android and Emscripten are always fullscreen
+#if !defined(__ANDROID__) || !defined(__IPHONEOS__) || !defined(__EMSCRIPTEN__) // Android, iOS and Emscripten are always fullscreen
add( "FULLSCREEN", page_id, to_translation( "Fullscreen" ),
to_translation( "Starts Cataclysm in one of the fullscreen modes. Requires restart." ),
{ { "no", to_translation( "No" ) }, { "maximized", to_translation( "Maximized" ) }, { "fullscreen", to_translation( "Fullscreen" ) }, { "windowedbl", to_translation( "Windowed borderless" ) } },
@@ -2650,6 +2650,14 @@ void options_manager::add_options_graphics()
break;
}
}
+# endif
+# if defined(__IPHONEOS__)
+ for( const id_and_option &renderer : renderer_list ) {
+ if( renderer.first == "meta" ) {
+ default_renderer = renderer.first;
+ break;
+ }
+ }
# endif
add( "RENDERER", page_id, to_translation( "Renderer" ),
to_translation( "Set which renderer to use. Requires restart." ), renderer_list,
@@ -2698,7 +2706,7 @@ void options_manager::add_options_graphics()
},
"none", COPT_CURSES_HIDE );
-#if !defined(__ANDROID__)
+#if !defined(__ANDROID__) || !defined(__IPHONEOS__)
add( "SCALING_FACTOR", page_id, to_translation( "Scaling factor" ),
to_translation( "Factor by which to scale the display. Requires restart." ), {
{ "1", to_translation( "1x" )},
@@ -2977,7 +2985,7 @@ void options_manager::add_options_debug()
void options_manager::add_options_android()
{
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
const auto add_empty_line = [&]() {
this->add_empty_line( "android" );
};
@@ -2990,9 +2998,10 @@ void options_manager::add_options_android()
add_empty_line();
add_option_group( "android", Group( "android_keyboard_opts",
- to_translation( "Android keyboard options" ),
- to_translation( "Options regarding Android keyboard." ) ),
+ to_translation( "Keyboard options" ),
+ to_translation( "Options regarding keyboard." ) ),
[&]( const std::string & page_id ) {
+#if defined(__ANDROID__)
add( "ANDROID_TRAP_BACK_BUTTON", page_id, to_translation( "Trap Back button" ),
to_translation( "If true, the back button will NOT back out of the app and will be passed to the application as SDL_SCANCODE_AC_BACK. Requires restart." ),
// take default setting from pre-game settings screen - important as there are issues with Back button on Android 9 with specific devices
@@ -3004,6 +3013,7 @@ void options_manager::add_options_android()
"such as popup messages and yes/no dialogs." ),
android_get_default_setting( "Native Android UI", true )
);
+#endif
add( "ANDROID_AUTO_KEYBOARD", page_id, to_translation( "Auto-manage virtual keyboard" ),
to_translation( "If true, automatically show/hide the virtual keyboard when necessary based on context. If false, virtual keyboard must be toggled manually." ),
@@ -3262,7 +3272,6 @@ void options_manager::add_options_android()
50, 1000, 130
);
} );
-
#endif
}
@@ -3994,7 +4003,7 @@ std::string options_manager::show( bool ingame, const bool world_options_only, b
calendar::set_eternal_night( ::get_option( "ETERNAL_TIME_OF_DAY" ) == "night" );
calendar::set_eternal_day( ::get_option( "ETERNAL_TIME_OF_DAY" ) == "day" );
-#if !defined(EMSCRIPTEN) && !defined(__ANDROID__) && !defined(TUI)
+#if !defined(EMSCRIPTEN) && !defined(__ANDROID__) && !defined(__IPHONEOS__) && !defined(TUI)
if( terminal_size_changed ) {
int scaling_factor = get_scaling_factor();
point TERM( ::get_option( "TERMINAL_X" ), ::get_option( "TERMINAL_Y" ) );
diff --git a/src/overmap_ui.cpp b/src/overmap_ui.cpp
index 9eeed620ec0f0..36b36a07d7f58 100644
--- a/src/overmap_ui.cpp
+++ b/src/overmap_ui.cpp
@@ -87,7 +87,7 @@ static const oter_type_str_id oter_type_forest_trail( "forest_trail" );
static const trait_id trait_DEBUG_CLAIRVOYANCE( "DEBUG_CLAIRVOYANCE" );
static const trait_id trait_DEBUG_NIGHTVISION( "DEBUG_NIGHTVISION" );
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
#include
#endif
diff --git a/src/path_info.cpp b/src/path_info.cpp
index bea276a06918e..6373723da8e0b 100644
--- a/src/path_info.cpp
+++ b/src/path_info.cpp
@@ -229,7 +229,11 @@ cata_path PATH_INFO::base_path()
}
std::string PATH_INFO::cache_dir()
{
+#if defined(__IPHONEOS__)
+ return std::string( getenv( "HOME" ) ) + "/Library/Cache/"
+#else
return datadir_value + "cache/";
+#endif
}
cata_path PATH_INFO::colors()
{
diff --git a/src/player_difficulty.h b/src/player_difficulty.h
index 0d927a1be72c0..dd623563b9a13 100644
--- a/src/player_difficulty.h
+++ b/src/player_difficulty.h
@@ -2,7 +2,7 @@
#ifndef CATA_SRC_PLAYER_DIFFICULTY_H
#define CATA_SRC_PLAYER_DIFFICULTY_H
-#include
+#include "npc.h"
// The point after which stats cost double
constexpr int HIGH_STAT = 12;
diff --git a/src/profession.cpp b/src/profession.cpp
index 7356e1e01349e..c2fe5fe02d599 100644
--- a/src/profession.cpp
+++ b/src/profession.cpp
@@ -29,8 +29,8 @@
#include "translations.h"
#include "type_id.h"
#include "visitable.h"
-#include
-#include
+#include "trait_group.h"
+#include "npc_class.h"
static const achievement_id achievement_achievement_arcade_mode( "achievement_arcade_mode" );
static const trait_group::Trait_group_tag
diff --git a/src/savegame.cpp b/src/savegame.cpp
index 3508f47d146d3..4379aa3cac879 100644
--- a/src/savegame.cpp
+++ b/src/savegame.cpp
@@ -59,7 +59,7 @@ static const oter_str_id oter_omt_obsolete( "omt_obsolete" );
static const string_id overmap_connection_local_road( "local_road" );
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
#include "input.h"
extern std::map> quick_shortcuts_map;
@@ -318,7 +318,7 @@ void scent_map::deserialize( const std::string &data, bool is_type )
}
}
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
///// quick shortcuts
void game::load_shortcuts( const cata_path &path )
{
diff --git a/src/sdltiles.cpp b/src/sdltiles.cpp
index efff97cc498f5..8d07f561f8435 100644
--- a/src/sdltiles.cpp
+++ b/src/sdltiles.cpp
@@ -90,7 +90,9 @@ std::unique_ptr imclient;
#if defined(__ANDROID__)
#include
+#endif
+#if defined(__IPHONEOS__) || defined(__ANDROID__)
#include "action.h"
#include "inventory.h"
#include "map.h"
@@ -99,6 +101,10 @@ std::unique_ptr imclient;
#include "worldfactory.h"
#endif
+#if defined(__IPHONEOS__)
+#include
+#endif
+
#if defined(EMSCRIPTEN)
#include
#endif
@@ -135,7 +141,7 @@ static SDL_Renderer_Ptr renderer;
static SDL_PixelFormat_Ptr format;
static SDL_Texture_Ptr display_buffer;
static GeometryRenderer_Ptr geometry;
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
static SDL_Texture_Ptr touch_joystick;
#endif
static int WindowWidth; //Width of the actual window, not the curses window
@@ -250,7 +256,7 @@ static void WinCreate()
SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, get_option( "SCALING_MODE" ).c_str() );
}
-#if !defined(__ANDROID__) && !defined(EMSCRIPTEN)
+#if !defined(__ANDROID__) && !defined(__IPHONEOS__) && !defined(EMSCRIPTEN)
if( get_option( "FULLSCREEN" ) == "fullscreen" ) {
window_flags |= SDL_WINDOW_FULLSCREEN;
fullscreen = true;
@@ -270,7 +276,8 @@ static void WinCreate()
// Without this, the game only displays in the top-left 1/4 of the window.
window_flags &= ~SDL_WINDOW_ALLOW_HIGHDPI;
#endif
-#if defined(__ANDROID__)
+
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
// Without this, the game only displays in the top-left 1/4 of the window.
window_flags = SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_MAXIMIZED;
#endif
@@ -280,7 +287,7 @@ static void WinCreate()
display = 0;
}
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
// Bugfix for red screen on Samsung S3/Mali
// https://forums.libsdl.org/viewtopic.php?t=11445
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
@@ -288,18 +295,22 @@ static void WinCreate()
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
// Fix Back button crash on Android 9
-#if defined(SDL_HINT_ANDROID_TRAP_BACK_BUTTON )
+#if defined(SDL_HINT_ANDROID_TRAP_BACK_BUTTON ) && !defined(__IPHONEOS__)
const bool trap_back_button = get_option( "ANDROID_TRAP_BACK_BUTTON" );
SDL_SetHint( SDL_HINT_ANDROID_TRAP_BACK_BUTTON, trap_back_button ? "1" : "0" );
#endif
// Prevent mouse|touch input confusion
-#if defined(SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH)
+#if defined(SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH) && !defined(__IPHONEOS__)
SDL_SetHint( SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, "1" );
#else
SDL_SetHint( SDL_HINT_MOUSE_TOUCH_EVENTS, "0" );
SDL_SetHint( SDL_HINT_TOUCH_MOUSE_EVENTS, "0" );
#endif
+
+#if defined(SDL_HINT_IOS_HIDE_HOME_INDICATOR)
+ SDL_SetHint( SDL_HINT_IOS_HIDE_HOME_INDICATOR, "1" );
+#endif
#endif
::window.reset( SDL_CreateWindow( "",
@@ -311,7 +322,7 @@ static void WinCreate()
) );
throwErrorIf( !::window, "SDL_CreateWindow failed" );
-#if !defined(__ANDROID__) && !defined(EMSCRIPTEN)
+#if !defined(__ANDROID__) || !defined(__IPHONEOS__) || !defined(EMSCRIPTEN)
// On Android SDL seems janky in windowed mode so we're fullscreen all the time.
// Fullscreen mode is now modified so it obeys terminal width/height, rather than
// overwriting it with this calculation.
@@ -389,17 +400,30 @@ static void WinCreate()
SDL_SetWindowMinimumSize( ::window.get(), fontwidth * EVEN_MINIMUM_TERM_WIDTH * scaling_factor,
fontheight * EVEN_MINIMUM_TERM_HEIGHT * scaling_factor );
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
// TODO: Not too sure why this works to make fullscreen on Android behave. :/
if( window_flags & SDL_WINDOW_FULLSCREEN || window_flags & SDL_WINDOW_FULLSCREEN_DESKTOP
|| window_flags & SDL_WINDOW_MAXIMIZED ) {
SDL_GetWindowSize( ::window.get(), &WindowWidth, &WindowHeight );
+#if defined(__IPHONEOS__)
+ WindowWidth = WindowWidth * 2;
+ WindowHeight = WindowHeight * 2;
+#endif
+ DebugLog( D_INFO, DC_ALL ) << "WindowWidth: " << WindowWidth;
+ DebugLog( D_INFO, DC_ALL ) << "WindowHeight: " << WindowHeight;
}
+#endif
+#if defined(__ANDROID__)
// Load virtual joystick texture
touch_joystick = CreateTextureFromSurface( renderer, load_image( "android/joystick.png" ) );
#endif
+#if defined(__IPHONEOS__)
+ // Load virtual joystick texture
+ touch_joystick = CreateTextureFromSurface( renderer, load_image( "ios/joystick.png" ) );
+#endif
+
ClearScreen();
// Errors here are ignored, worst case: the option does not work as expected,
@@ -431,7 +455,7 @@ static void WinCreate()
static void WinDestroy()
{
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
touch_joystick.reset();
#endif
imclient.reset();
@@ -451,7 +475,7 @@ static const SDL_Color &color_as_sdl( const unsigned char color )
return windowsPalette[color];
}
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
void draw_terminal_size_preview();
void draw_quick_shortcuts();
void draw_virtual_joystick();
@@ -469,6 +493,8 @@ extern "C" {
static bool has_visible_display_frame = false;
static SDL_Rect visible_display_frame;
+ // TODO: get this thing to work on iOS
+#if defined(__ANDROID__)
JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeVisibleDisplayFrameChanged(
JNIEnv *env, jclass jcls, jint left, jint top, jint right, jint bottom )
{
@@ -481,7 +507,7 @@ extern "C" {
visible_display_frame.w = right - left;
visible_display_frame.h = bottom - top;
}
-
+#endif
} // "C"
SDL_Rect get_android_render_rect( float DisplayBufferWidth, float DisplayBufferHeight )
@@ -507,9 +533,8 @@ SDL_Rect get_android_render_rect( float DisplayBufferWidth, float DisplayBufferH
dstrect.w = WindowHeightLessShortcuts * DisplayBufferAspect;
dstrect.h = WindowHeightLessShortcuts;
}
-
// Make sure the destination rectangle fits within the visible area
- if( get_option( "ANDROID_KEYBOARD_SCREEN_SCALE" ) && has_visible_display_frame ) {
+/* if( get_option( "ANDROID_KEYBOARD_SCREEN_SCALE" ) && has_visible_display_frame ) {
int vdf_right = visible_display_frame.x + visible_display_frame.w;
int vdf_bottom = visible_display_frame.y + visible_display_frame.h;
if( vdf_right < dstrect.x + dstrect.w ) {
@@ -518,10 +543,14 @@ SDL_Rect get_android_render_rect( float DisplayBufferWidth, float DisplayBufferH
if( vdf_bottom < dstrect.y + dstrect.h ) {
dstrect.h = vdf_bottom - dstrect.y;
}
- }
+ } */
+ DebugLog( D_INFO, DC_ALL ) << "dstrect.x: " << dstrect.x;
+ DebugLog( D_INFO, DC_ALL ) << "dstrect.y: " << dstrect.y;
+ DebugLog( D_INFO, DC_ALL ) << "dstrect.w: " << dstrect.w;
+ DebugLog( D_INFO, DC_ALL ) << "dstrect.h: " << dstrect.h;
+
return dstrect;
}
-
#endif
void refresh_display()
@@ -537,7 +566,7 @@ void refresh_display()
// there, present it, select the buffer as target again.
SetRenderTarget( renderer, nullptr );
ClearScreen();
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
SDL_Rect dstrect = get_android_render_rect( TERMINAL_WIDTH * fontwidth,
TERMINAL_HEIGHT * fontheight );
RenderCopy( renderer, display_buffer, NULL, &dstrect );
@@ -545,7 +574,7 @@ void refresh_display()
RenderCopy( renderer, display_buffer, nullptr, nullptr );
#endif
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
draw_terminal_size_preview();
if( g ) {
draw_quick_shortcuts();
@@ -751,7 +780,7 @@ void cata_tiles::draw_om( const point &dest, const tripoint_abs_omt ¢er_abs_
return;
}
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
// Attempted bugfix for Google Play crash - prevent divide-by-zero if no tile
// width/height specified
if( tile_width == 0 || tile_height == 0 ) {
@@ -1854,7 +1883,7 @@ void toggle_fullscreen_window()
fullscreen = !fullscreen;
}
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
static float finger_down_x = -1.0f; // in pixels
static float finger_down_y = -1.0f; // in pixels
static float finger_curr_x = -1.0f; // in pixels
@@ -1908,6 +1937,7 @@ std::string get_quick_shortcut_name( const std::string &category )
float android_get_display_density()
{
+#if defined(__ANDROID__)
JNIEnv *env = ( JNIEnv * )SDL_AndroidGetJNIEnv();
jobject activity = ( jobject )SDL_AndroidGetActivity();
jclass clazz( env->GetObjectClass( activity ) );
@@ -1915,6 +1945,10 @@ float android_get_display_density()
jfloat ans = env->CallFloatMethod( activity, method_id );
env->DeleteLocalRef( activity );
env->DeleteLocalRef( clazz );
+#endif
+#if defined(__IPHONEOS__)
+ float ans = CataclysmExperimental::iosGetDisplayDensity();
+#endif
return ans;
}
@@ -2400,7 +2434,6 @@ void draw_quick_shortcuts()
void draw_virtual_joystick()
{
-
// Bail out if we don't need to draw the joystick
if( !get_option( "ANDROID_SHOW_VIRTUAL_JOYSTICK" ) ||
finger_down_time <= 0 ||
@@ -2412,6 +2445,8 @@ void draw_virtual_joystick()
return;
}
+ dbg( D_INFO ) << "Drawing virtual joystick";
+
SDL_SetTextureAlphaMod( touch_joystick.get(),
get_option( "ANDROID_VIRTUAL_JOYSTICK_OPACITY" ) * 0.01f * 255.0f );
@@ -2570,6 +2605,7 @@ void handle_finger_input( uint32_t ticks )
bool android_is_hardware_keyboard_available()
{
+#if defined(__ANDROID__)
JNIEnv *env = ( JNIEnv * )SDL_AndroidGetJNIEnv();
jobject activity = ( jobject )SDL_AndroidGetActivity();
jclass clazz( env->GetObjectClass( activity ) );
@@ -2577,6 +2613,10 @@ bool android_is_hardware_keyboard_available()
jboolean ans = env->CallBooleanMethod( activity, method_id );
env->DeleteLocalRef( activity );
env->DeleteLocalRef( clazz );
+#endif
+#if defined(__IPHONEOS__)
+ bool ans = CataclysmExperimental::isIOSKeyBoardAvailable();
+#endif
return ans;
}
@@ -2584,6 +2624,7 @@ void android_vibrate()
{
int vibration_ms = get_option( "ANDROID_VIBRATION" );
if( vibration_ms > 0 && !android_is_hardware_keyboard_available() ) {
+#if defined(__ANDROID__)
JNIEnv *env = ( JNIEnv * )SDL_AndroidGetJNIEnv();
jobject activity = ( jobject )SDL_AndroidGetActivity();
jclass clazz( env->GetObjectClass( activity ) );
@@ -2591,11 +2632,15 @@ void android_vibrate()
env->CallVoidMethod( activity, method_id, vibration_ms );
env->DeleteLocalRef( activity );
env->DeleteLocalRef( clazz );
+#endif
+#if defined(__IPHONEOS__)
+ CataclysmExperimental::vibrateDevice();
+#endif
}
}
#endif
-#if !defined(__ANDROID__)
+#if !defined(__ANDROID__) || !defined(__IPHONEOS__)
static bool window_focus = false;
static bool text_input_active_when_regaining_focus = false;
#endif
@@ -2606,7 +2651,7 @@ void StartTextInput()
if( SDL_IsTextInputActive() == SDL_TRUE ) {
return;
}
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
SDL_StartTextInput();
#else
if( window_focus ) {
@@ -2619,7 +2664,7 @@ void StartTextInput()
void StopTextInput()
{
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
SDL_StopTextInput();
#else
if( window_focus ) {
@@ -2638,7 +2683,7 @@ static void CheckMessages()
bool text_refresh = false;
bool is_repeat = false;
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
if( visible_display_frame_dirty ) {
needupdate = true;
ui_manager::redraw_invalidated();
@@ -2651,7 +2696,7 @@ static void CheckMessages()
if( android_is_hardware_keyboard_available() && !SDL_IsTextInputActive() ) {
StartTextInput();
}
-
+#if defined(__ANDROID__)
// Make sure the SDL surface view is visible, otherwise the "Z" loading screen is visible.
if( needs_sdl_surface_visibility_refresh ) {
needs_sdl_surface_visibility_refresh = false;
@@ -2665,6 +2710,7 @@ static void CheckMessages()
env->DeleteLocalRef( activity );
env->DeleteLocalRef( clazz );
}
+#endif
// Copy the current input context
if( !input_context::input_context_stack.empty() ) {
@@ -2883,15 +2929,17 @@ static void CheckMessages()
// Display an Android toast message
{
- JNIEnv *env = ( JNIEnv * )SDL_AndroidGetJNIEnv();
- jobject activity = ( jobject )SDL_AndroidGetActivity();
- jclass clazz( env->GetObjectClass( activity ) );
- jstring toast_message = env->NewStringUTF( quick_shortcuts_enabled ? "Shortcuts visible" :
- "Shortcuts hidden" );
- jmethodID method_id = env->GetMethodID( clazz, "toast", "(Ljava/lang/String;)V" );
- env->CallVoidMethod( activity, method_id, toast_message );
- env->DeleteLocalRef( activity );
- env->DeleteLocalRef( clazz );
+#if defined(__ANDROID__)
+ JNIEnv *env = ( JNIEnv * )SDL_AndroidGetJNIEnv();
+ jobject activity = ( jobject )SDL_AndroidGetActivity();
+ jclass clazz( env->GetObjectClass( activity ) );
+ jstring toast_message = env->NewStringUTF( quick_shortcuts_enabled ? "Shortcuts visible" :
+ "Shortcuts hidden" );
+ jmethodID method_id = env->GetMethodID( clazz, "toast", "(Ljava/lang/String;)V" );
+ env->CallVoidMethod( activity, method_id, toast_message );
+ env->DeleteLocalRef( activity );
+ env->DeleteLocalRef( clazz );
+#endif
}
}
}
@@ -2944,7 +2992,7 @@ static void CheckMessages()
}
}
#endif
-
+
last_input = input_event();
std::optional resize_dims;
@@ -2955,7 +3003,7 @@ static void CheckMessages()
switch( ev.type ) {
case SDL_WINDOWEVENT:
switch( ev.window.event ) {
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
// SDL will send a focus lost event whenever the app loses focus (eg. lock screen, switch app focus etc.)
// If we detect it and the game seems in a saveable state, try and do a quicksave. This is a bit dodgy
// as the player could be ANYWHERE doing ANYTHING (a sub-menu, interacting with an NPC/computer etc.)
@@ -2986,7 +3034,7 @@ static void CheckMessages()
if( SDL_IsTextInputActive() ) {
text_input_active_when_regaining_focus = true;
// Stop text input to not intefere with other programs
- SDL_StopTextInput();
+ StopTextInput();
// Clear uncommited IME text. TODO: commit IME text instead.
last_input = input_event();
last_input.type = input_event_t::keyboard_char;
@@ -3012,7 +3060,7 @@ static void CheckMessages()
needupdate = true;
break;
case SDL_WINDOWEVENT_RESTORED:
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
needs_sdl_surface_visibility_refresh = true;
if( android_is_hardware_keyboard_available() ) {
StopTextInput();
@@ -3027,11 +3075,45 @@ static void CheckMessages()
break;
}
break;
+#if defined(__IPHONEOS__)
+ case SDL_APP_WILLENTERBACKGROUND:
+ if( world_generator &&
+ world_generator->active_world &&
+ g && g->uquit == QUIT_NO &&
+ !std::uncaught_exception() ) {
+ g->quicksave();
+ }
+ if( SDL_IsTextInputActive() ) {
+ // TODO: Abstract common method with above usage
+ text_input_active_when_regaining_focus = true;
+ // Stop text input to not intefere with other programs
+ StopTextInput();
+ // Clear uncommited IME text. TODO: commit IME text instead.
+ last_input = input_event();
+ last_input.type = input_event_t::keyboard_char;
+ last_input.edit.clear();
+ last_input.edit_refresh = true;
+ text_refresh = true;
+ } else {
+ text_input_active_when_regaining_focus = false;
+ }
+ break;
+ case SDL_APP_DIDENTERBACKGROUND:
+ window_focus = false;
+ break;
+ case SDL_APP_DIDENTERFOREGROUND:
+ window_focus = true;
+ // Restore text input status
+ if( !SDL_IsTextInputActive() || text_input_active_when_regaining_focus ) {
+ SDL_StartTextInput();
+ }
+ break;
+#endif
case SDL_RENDER_TARGETS_RESET:
render_target_reset = true;
break;
case SDL_KEYDOWN: {
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
// Toggle virtual keyboard with Android back button. For some reason I get double inputs, so ignore everything once it's already down.
if( ev.key.keysym.sym == SDLK_AC_BACK && ac_back_down_time == 0 ) {
ac_back_down_time = ticks;
@@ -3044,7 +3126,7 @@ static void CheckMessages()
SDL_ShowCursor( SDL_DISABLE );
}
keyboard_mode mode = keyboard_mode::keychar;
-#if !defined(__ANDROID__) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1)
+#if !defined(__ANDROID__) && !defined(__IPHONEOS__)
if( !SDL_IsTextInputActive() ) {
mode = keyboard_mode::keycode;
}
@@ -3058,7 +3140,7 @@ static void CheckMessages()
// key was handled
} else {
last_input = input_event( lc, input_event_t::keyboard_char );
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
if( !android_is_hardware_keyboard_available() ) {
if( !is_string_input( touch_input_context ) && !touch_input_context.allow_text_entry ) {
if( get_option( "ANDROID_AUTO_KEYBOARD" ) ) {
@@ -3102,7 +3184,7 @@ static void CheckMessages()
}
#endif
keyboard_mode mode = keyboard_mode::keychar;
-#if !defined(__ANDROID__) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1)
+#if !defined(__ANDROID__) && !defined(__IPHONEOS__)
if( !SDL_IsTextInputActive() ) {
mode = keyboard_mode::keycode;
}
@@ -3126,7 +3208,7 @@ static void CheckMessages()
if( strlen( ev.text.text ) > 0 ) {
const unsigned lc = UTF8_getch( ev.text.text );
last_input = input_event( lc, input_event_t::keyboard_char );
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
if( !android_is_hardware_keyboard_available() ) {
if( !is_string_input( touch_input_context ) && !touch_input_context.allow_text_entry ) {
if( get_option( "ANDROID_AUTO_KEYBOARD" ) ) {
@@ -3257,10 +3339,14 @@ static void CheckMessages()
}
break;
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
case SDL_FINGERMOTION:
+ dbg( D_INFO ) << "Fingermotion triggered.";
+ dbg( D_INFO ) << "ev.tfinger.fingerId: " << ev.tfinger.fingerId;
+ dbg( D_INFO ) << "ev.tfinger.touchId: " << ev.tfinger.touchId;
if( ev.tfinger.fingerId == 0 ) {
if( !is_quick_shortcut_touch ) {
+ dbg( D_INFO ) << "Not quick shortcut touch";
update_finger_repeat_delay();
}
needupdate = true; // ensure virtual joystick and quick shortcuts redraw as we interact
@@ -3292,13 +3378,19 @@ static void CheckMessages()
}
break;
case SDL_FINGERDOWN:
+ dbg( D_INFO ) << "Fingerdown triggered.";
+ dbg( D_INFO ) << "ev.tfinger.fingerId: " << ev.tfinger.fingerId;
+ dbg( D_INFO ) << "ev.tfinger.touchId: " << ev.tfinger.touchId;
if( ev.tfinger.fingerId == 0 ) {
finger_down_x = finger_curr_x = ev.tfinger.x * WindowWidth;
finger_down_y = finger_curr_y = ev.tfinger.y * WindowHeight;
finger_down_time = ticks;
finger_repeat_time = 0;
is_quick_shortcut_touch = get_quick_shortcut_under_finger() != NULL;
+ DebugLog( D_INFO, DC_ALL ) << "finger_down_x: " << finger_down_x;
+ DebugLog( D_INFO, DC_ALL ) << "finger_down_y: " << finger_down_y;
if( !is_quick_shortcut_touch ) {
+ dbg( D_INFO ) << "Not quick shortcut touch";
update_finger_repeat_delay();
}
ui_manager::redraw_invalidated();
@@ -3307,6 +3399,8 @@ static void CheckMessages()
if( !is_quick_shortcut_touch ) {
second_finger_down_x = second_finger_curr_x = ev.tfinger.x * WindowWidth;
second_finger_down_y = second_finger_curr_y = ev.tfinger.y * WindowHeight;
+ DebugLog( D_INFO, DC_ALL ) << "second_finger_curr_x: " << finger_down_x;
+ DebugLog( D_INFO, DC_ALL ) << "second_finger_curr_y: " << second_finger_curr_y;
is_two_finger_touch = true;
}
} else if( ev.tfinger.fingerId == 2 ) {
@@ -3319,9 +3413,14 @@ static void CheckMessages()
}
break;
case SDL_FINGERUP:
+ dbg( D_INFO ) << "Fingerup triggered.";
+ dbg( D_INFO ) << "ev.tfinger.fingerId: " << ev.tfinger.fingerId;
+ dbg( D_INFO ) << "ev.tfinger.touchId: " << ev.tfinger.touchId;
if( ev.tfinger.fingerId == 0 ) {
finger_curr_x = ev.tfinger.x * WindowWidth;
finger_curr_y = ev.tfinger.y * WindowHeight;
+ DebugLog( D_INFO, DC_ALL ) << "finger_curr_x: " << finger_curr_x;
+ DebugLog( D_INFO, DC_ALL ) << "finger_curr_y: " << finger_curr_y;
if( is_quick_shortcut_touch ) {
input_event *quick_shortcut = get_quick_shortcut_under_finger();
if( quick_shortcut ) {
@@ -3431,9 +3530,10 @@ static void CheckMessages()
quick_shortcuts_enabled = !quick_shortcuts_enabled;
quick_shortcuts_toggle_handled = true;
-
+ //TODO: get some equivalent to iOS
// Display an Android toast message
{
+#if defined(__ANDROID__)
JNIEnv *env = ( JNIEnv * )SDL_AndroidGetJNIEnv();
jobject activity = ( jobject )SDL_AndroidGetActivity();
jclass clazz( env->GetObjectClass( activity ) );
@@ -3443,6 +3543,7 @@ static void CheckMessages()
env->CallVoidMethod( activity, method_id, toast_message );
env->DeleteLocalRef( activity );
env->DeleteLocalRef( clazz );
+#endif
}
} else {
last_input = input_event( three_tap_key, input_event_t::keyboard_char );
@@ -3565,7 +3666,7 @@ static void init_term_size_and_scaling_factor()
scaling_factor = 1;
point terminal( get_option( "TERMINAL_X" ), get_option( "TERMINAL_Y" ) );
-#if !defined(__ANDROID__)
+#if !defined(__ANDROID__) || !defined(__IPHONEOS__)
if( get_option( "SCALING_FACTOR" ) == "2" ) {
scaling_factor = 2;
@@ -3759,7 +3860,7 @@ void catacurses::init_interface()
stdscr = newwin( get_terminal_height(), get_terminal_width(), point::zero );
//newwin calls `new WINDOW`, and that will throw, but not return nullptr.
imclient->load_fonts( gui_font, font, windowsPalette, fl.gui_typeface, fl.typeface );
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
// Make sure we initialize preview_terminal_width/height to sensible values
preview_terminal_width = TERMINAL_WIDTH * fontwidth;
preview_terminal_height = TERMINAL_HEIGHT * fontheight;
@@ -3845,7 +3946,7 @@ input_event input_manager::get_input_event( const keyboard_mode preferred_keyboa
throw std::runtime_error( "input_manager::get_input_event called in test mode" );
}
-#if !defined(__ANDROID__) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1)
+#if !defined(__ANDROID__) && !defined(__IPHONEOS__)
if( actual_keyboard_mode( preferred_keyboard_mode ) == keyboard_mode::keychar ) {
StartTextInput();
} else {
@@ -3903,11 +4004,11 @@ input_event input_manager::get_input_event( const keyboard_mode preferred_keyboa
SDL_GetMouseState( &last_input.mouse_pos.x, &last_input.mouse_pos.y );
if( last_input.type == input_event_t::keyboard_char ) {
previously_pressed_key = last_input.get_first_input();
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
android_vibrate();
#endif
}
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
else if( last_input.type == input_event_t::gamepad ) {
android_vibrate();
}
diff --git a/src/sdltiles.h b/src/sdltiles.h
index 2617b6716a08e..60177bc597ffb 100644
--- a/src/sdltiles.h
+++ b/src/sdltiles.h
@@ -19,11 +19,6 @@ class window;
#include "sdl_wrappers.h"
#include "string_id.h"
-#if defined(__APPLE__)
-// For TARGET_OS_IPHONE macro to test if is on iOS
-#include
-#endif
-
class cata_tiles;
struct weather_type;
diff --git a/src/string_editor_window.cpp b/src/string_editor_window.cpp
index 0b89d488f0f91..3a77706ec79ed 100644
--- a/src/string_editor_window.cpp
+++ b/src/string_editor_window.cpp
@@ -4,7 +4,7 @@
#include "sdl_wrappers.h"
#endif
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
#include
#include "cata_utility.h"
#include "options.h"
@@ -403,7 +403,7 @@ std::pair string_editor_window::query_string()
wnoutrefresh( _win );
} );
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
on_out_of_scope stop_text_input( []() {
if( get_option( "ANDROID_AUTO_KEYBOARD" ) ) {
StopTextInput();
diff --git a/src/string_input_popup.cpp b/src/string_input_popup.cpp
index d8143b8db5340..d74c82fa851b9 100644
--- a/src/string_input_popup.cpp
+++ b/src/string_input_popup.cpp
@@ -19,7 +19,7 @@
#include "sdl_wrappers.h"
#endif
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
#include
#include "options.h"
@@ -462,7 +462,7 @@ const std::string &string_input_popup::query_string( const bool loop, const bool
if( desc_view_ptr && desc_view_ptr->handle_navigation( action, *ctxt ) ) {
// NO FURTHER ACTION REQUIRED
} else if( action == "TEXT.QUIT" ) {
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
if( get_option( "ANDROID_AUTO_KEYBOARD" ) ) {
StopTextInput();
}
diff --git a/src/swift/ios_stuff.swift b/src/swift/ios_stuff.swift
new file mode 100644
index 0000000000000..df40d9dbccbe5
--- /dev/null
+++ b/src/swift/ios_stuff.swift
@@ -0,0 +1,36 @@
+import Foundation
+import GameController
+import UIKit
+import AVFoundation
+
+//https://stackoverflow.com/a/76728094
+extension UIWindow {
+ static var current: UIWindow? {
+ for scene in UIApplication.shared.connectedScenes {
+ guard let windowScene = scene as? UIWindowScene else { continue }
+ for window in windowScene.windows {
+ if window.isKeyWindow { return window }
+ }
+ }
+ return nil
+ }
+}
+
+extension UIScreen {
+ static var current: UIScreen? {
+ UIWindow.current?.screen
+ }
+}
+
+public func iosGetDisplayDensity() -> Float {
+ let scale = UIScreen.current?.nativeScale ?? 1.0
+ return Float(scale)
+}
+
+public func isIOSKeyBoardAvailable() -> Bool {
+ return GCKeyboard.coalesced != nil
+}
+
+public func vibrateDevice() {
+ AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
+}
diff --git a/src/ui.cpp b/src/ui.cpp
index 66b82a69761bb..fb9bf067516e7 100644
--- a/src/ui.cpp
+++ b/src/ui.cpp
@@ -27,6 +27,9 @@
#if defined(__ANDROID__)
#include
+#endif
+
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
#include
#include "options.h"
@@ -934,7 +937,7 @@ void uilist::query( bool loop, int timeout, bool allow_unfiltered_hotkeys )
shared_ptr_fast ui = create_or_get_ui();
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) || defined(__IPHONEOS__)
for( const auto &entry : entries ) {
if( entry.enabled && entry.hotkey.has_value()
&& entry.hotkey.value() != input_event() ) {
diff --git a/src/weather_type.cpp b/src/weather_type.cpp
index c7d1550dea9da..5edc91a9777a8 100644
--- a/src/weather_type.cpp
+++ b/src/weather_type.cpp
@@ -8,7 +8,7 @@
#include "debug.h"
#include "generic_factory.h"
#include "json.h"
-#include
+#include "weather.h"
namespace
{
diff --git a/tests/act_build_test.cpp b/tests/act_build_test.cpp
index 6ed7b6a7131ae..1a00e8bd906a8 100644
--- a/tests/act_build_test.cpp
+++ b/tests/act_build_test.cpp
@@ -295,4 +295,4 @@ TEST_CASE( "npc_act_multiple_construction", "[npc][zones][activities][constructi
u.set_body();
u.set_fac( faction_free_merchants );
run_test_case( u );
-}
+}
\ No newline at end of file