RingOfRaces/modules/godot_remote/README.md

19 KiB

Godot Remote

This is cross platform native module for Godot Engine v3 for control apps and games over WiFi or ADB.

If you are developing on a non-touch device, this module is the best way to quickly test touch input or test mobile sensors data.

Video Demonstration

Custom Packets Demo

Support

ko-fi

paypal

Compiling the Module

As a module

  1. configure environment to build editor for your platform (you need to clone 3.2 branch not master)
  2. copy godot_remote folder to the modules/ directory or make symlink
  3. compile engine with instructions from documentation above (e.g. scons p=windows tools=yes -j[place here count of your CPU threads])
  4. run bin/godot[based on config].

If everything compiles successfully, you'll find the new category in project settings Debug/Godot Remote where you can configure server.

Settings

As a GDNative library

  1. Configure environment to build editor for your platform
  2. Generate api.json for GDNative api. bin/godot --gdnative-generate-json-api api.json
  3. Copy api.json to the root directory of this repository
  4. Compile godot-cpp (e.g. in godot-cpp directory run scons generate_bindings=true platform=windows target=release bits=64 -j8 ../api.json)
  5. Compile module for your platform (Available platforms: windows, osx, linux, ios, android. Tested platforms: windows, linux, android)
    1. For android: Run in root directory [path to your android ndk root dir]/ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk APP_PLATFORM=android-21
    2. For all other platforms: scons platform=windows target=release -j8
  6. Use produced library in bin/

GDNative has limitations so here GodotRemote is not a singleton and you need to create autoload scene with attached NativeScript for GodotRemote class. Also there is no any settings in Debug/Godot Remote.

Enum constants in this version changed too (see [API Reference] )

Currently, the GDNative version does not support the assignment of sensor data, so the editor will not support accelerometer, gyroscope, etc. Also, this version may crash at a random moment.

If GDNative becomes more stable, I will add the necessary code to easily integrate this module into any project, but now it just works.. sometimes.

Additional parameters

Also module has additional compilation parameters for scons script

  1. godot_remote_no_default_resources (yes/no) default no - compile with or without default resources
  2. godot_remote_disable_server (yes/no) default no - do not include server code
  3. godot_remote_disable_client (yes/no) default no - do not include client code

Download

Precompiled binaries can be found on GitHub Releases page

Mobile app

On releases page you can found precompiled mobile app but also it can be downloaded from Google Play

Configure Mobile App

To open settings menu you need to touch the screen with 5 fingers at once.

Then you'll see this settings menu:

Settings

Important: after entering server address you should apply it by pressing Set Type and Address or Set Type and Port

Custom client

If need to support other platforms or you need a specific version of module integrated to the client app, you can build client from source code placed here.

If you don't want to use my client app you can check the example client project and build your own client.

Or you can donate me some money with request to buy iPhone and adapt a client for it 🙂

API Reference

Methods will be declared follows this template:

return_type function_name([arg_name1 : type [= defalut value]][, arg_name2 : type [= defalut value]])

Important: All enums in GDNative version is exposed in GodotRemote class because of limitations. For example, if you want to use StreamState.STREAM_ACTIVE from GRClient you need to get property GRClient_STREAM_ACTIVE of GodotRemote object

# Godot module:
GRClient.STREAM_ACTIVE:

# GDNative
# *GodotRemote is autoload scene with attached NativeScript
GodotRemote.GRClient_STREAM_ACTIVE

GodotRemote

Main class of module.

# --- Properties

# Canvas layer that shows notifications
# type int, default 128
notifications_layer

# Notifications position on screen
# type GRNotifications.NotificationsPosition, default TC
notifications_position

# Is notifications enabled
# type bool, default true
notifications_enabled

# Base duration for showing notifications
# type float, default 3.0
notifications_duration

# Notifcations style
# type GRNotificationStyle
notifications_style

# --- Methods

# Notifications

# Adds or fully update existing notification
# @title: Notification title
# @text: Text of notification
# @notification_icon: Notification icon from enum NotificationIcon
# @update_existing: Updates existing notification
# @duration_multiplier: Multiply base notifications duration
void add_notification(title: String, text: String, notification_icon: GRNotifications.NotificationIcon = 0, update_existing: bool = true, duration_multiplier: float = 1.0)

# Adds new notification or append text to existing notification
# @title: Notification title
# @text: Text of notification
# @icon: Notification icon from enum NotificationIcon
# @add_to_new_line: Adds text to new line or adds to current line
void add_notification_or_append_string(title: String, text: String, icon: GRNotifications.NotificationIcon, add_to_new_line: bool = true, duration_multiplier: float = 1.0)

# Adds notification or update one line of notification text
# @title: Notification title
# @id: Line ID
# @text: Text of notification
# @icon: Notification icon from enum NotificationIcon
# @duration_multiplier: Multiply base notifications duration
void add_notification_or_update_line(title: String, id: String, text: String, icon: GRNotifications.NotificationIcon, duration_multiplier: float = 1.0)

# Clear all notifications
void clear_notifications()

# Get notifications list
# @return list of all visible notifications
Array get_all_notifications()

# Get notification with specified title or null
# @title: Notification title
# @return matched notification
GRNotificationPanel get_notification(title: String)

# Get all notifications with specified title
# @title: Notification title
# @return list of visible notifications
Array get_notifications_with_title(title: String)

# Remove notifications with specified title
# @title: Notifications title
# @is_all_entries: Delete all notifications with @title if true
void remove_notification(title: String, is_all_entries: bool = true)

# Remove exact notification by reference
# @notification: Notification reference
void remove_notification_exact(notification: Node)

# Client/Server

# Create device: client or server
# @device_type: Type of device
# @return true if device created successful
bool create_remote_device(device_type: GodotRemote.DeviceType = 0)

# Start device
# @return true if device valid
bool start_remote_device()

# Create and start device
# @device_type: Type of device
void create_and_start_device(device_type: GodotRemote.DeviceType = 0)

# Remove and delete currently working device
# @return true if succeed
bool remove_remote_device()

# Get device
# @return client, server or null
GRDevice get_device()

# Utility functions

# Not exposed to GDScript fuctions from Input class
# And currently not available in GDNative
void set_accelerometer(value: Vector3)
void set_gravity(value: Vector3)
void set_gyroscope(value: Vector3)
void set_magnetometer(value: Vector3)

# Set GodotRemote log level
# @level: Level of logging
void set_log_level(level: LogLevel)

# Get GodotRemote module version
# @return module version in format "MAJOR.MINOR.BUILD"
String get_version()

# --- Signals

# Device added
device_added()

# Device removed
device_removed()

# --- Enumerations

DeviceType:
    DEVICE_AUTO = 0
    DEVICE_SERVER = 1
    DEVICE_CLIENT = 2

LogLevel:
    LL_NONE = 4
    LL_DEBUG = 0
    LL_NORMAL = 1
    LL_WARNING = 2
    LL_ERROR = 3

GRNotifications

Container for all notifications


# --- Signals

# Called when a single notification is added
notification_added(title: String, text: String)

# Called when a single notification is removed
notification_removed(title: String, is_cleared: bool)

# Called when all notifications are cleared
notifications_cleared()

# Called when notifications are enabled or disabled
notifications_toggled(is_enabled: bool)

# --- Enumerations

NotificationIcon:
    ICON_NONE = 0
    ICON_ERROR = 1
    ICON_WARNING = 2
    ICON_SUCCESS = 3
    ICON_FAIL = 4

NotificationsPosition:
    TOP_LEFT = 0
    TOP_CENTER = 1
    TOP_RIGHT = 2
    BOTTOM_LEFT = 3
    BOTTOM_CENTER = 4
    BOTTOM_RIGHT = 5

GRNotificationStyle

Helper class to store parameters of notifications style

# --- Properties

# Style of background notifications panel
# type StyleBox
panel_style

# Theme for notification close button
# type Theme
close_button_theme

# Close button icon texture
# type Texture
close_button_icon

# Notification title font
# type Font
title_font

# Notification text font
# type Font
text_font

# --- Methods

# Get notification icon from this style
# @notification_icon: Notfication icon id
# @return icon texture of null
Texture get_notification_icon(notification_icon: GRNotifications.NotificationIcon)

# Set notification icon in this style
# @notification_icon: Notfication icon id
# @icon_texture: Icon texture
void set_notification_icon(notification_icon: GRNotifications.NotificationIcon, icon_texture: Texture)

GRInputData

Container for all InputEvents

# --- Enumerations

InputType:
    _NoneIT = 0
    _InputDeviceSensors = 1
    _InputEvent = 64
    _InputEventAction = 65
    _InputEventGesture = 66
    _InputEventJoypadButton = 67
    _InputEventJoypadMotion = 68
    _InputEventKey = 69
    _InputEventMagnifyGesture = 70
    _InputEventMIDI = 71
    _InputEventMouse = 72
    _InputEventMouseButton = 73
    _InputEventMouseMotion = 74
    _InputEventPanGesture = 75
    _InputEventScreenDrag = 76
    _InputEventScreenTouch = 77
    _InputEventWithModifiers = 78
    _InputEventMAX = 79

GRPacket

The basic data type used to exchange information between the client and the server

# --- Enumerations

PacketType:
    NonePacket = 0
    SyncTime = 1
    ImageData = 2
    InputData = 3
    ServerSettings = 4
    MouseModeSync = 5
    CustomInputScene = 6
    ClientStreamOrientation = 7
    ClientStreamAspect = 8
    CustomUserData = 9
    Ping = 128
    Pong = 192

GRDevice

Base class for client and server

# --- Properties

# Connection port
# type int, default 52341
port

# --- Methods

# Send user data to remote device
# @packet_id: any data to identify your packet
# @user_data: any data to send to remote device
# @full_objects: flag for full serialization of objects, possibly with their executable code. For more info check Godot's PacketPeer.put_var() and PacketPeer.get_var()
void send_user_data(packet_id: Variant, user_data: Variant, full_objects: bool = false)

# Get average FPS
# @return average FPS
float get_avg_fps()

# Get minimum FPS
# @return minimum FPS
float get_min_fps()

# Get maximum FPS
# @return maximum FPS
float get_max_fps()

# Get average ping
# @return average ping
float get_avg_ping()

# Get minimum ping
# @return minimum ping
float get_min_ping()

# Get maximum ping
# @return maximum ping
float get_max_ping()

# Get device status
WorkingStatus get_status()

# Start device
void start()

# Stop device
void stop()

# --- Signals

# Device status changed
status_changed(status: GRDevice.WorkingStatus)

# User data received from a remote device
user_data_received(packet_id: Variant, user_data: Variant)

# --- Enumerations

ImageCompressionType:
    COMPRESSION_UNCOMPRESSED = 0
    COMPRESSION_JPG = 1
    COMPRESSION_PNG = 2

Subsampling:
    SUBSAMPLING_Y_ONLY = 0
    SUBSAMPLING_H1V1 = 1
    SUBSAMPLING_H2V1 = 2
    SUBSAMPLING_H2V2 = 3

TypesOfServerSettings:
    SERVER_SETTINGS_USE_INTERNAL = 0
    SERVER_SETTINGS_VIDEO_STREAM_ENABLED = 1
    SERVER_SETTINGS_COMPRESSION_TYPE = 2
    SERVER_SETTINGS_JPG_QUALITY = 3
    SERVER_SETTINGS_SKIP_FRAMES = 4
    SERVER_SETTINGS_RENDER_SCALE = 5

WorkingStatus:
    STATUS_STARTING = 3
    STATUS_STOPPING = 2
    STATUS_WORKING = 1
    STATUS_STOPPED = 0

GRServer

# --- Properties

# Server password
# type String, default ""
password

# Path to the custom input scene.
# type String, default ""
custom_input_scene

# Is custom input scene compressed
## Doesn't work in GDNative
# type bool, default true
custom_input_scene_compressed

# Compression type of custom input scene
## Doesn't work in GDNative
# type File.CompressionMode, default FastLZ
custom_input_scene_compression_type

# --- Methods

# Set whether the stream is enabled
bool set_video_stream_enabled(value : bool)

# Get whether the stream is enabled
bool is_video_stream_enabled()

# Set how many frames to skip
bool set_skip_frames(frames : int)

# Get the number of skipping frames
int get_skip_frames()

# Set JPG quality
bool set_jpg_quality(quality : int)

# Get JPG quality
int get_jpg_quality()

# Set the scale of the stream
bool set_render_scale(scale : float)

# Get stream scale
float get_render_scale()

# Force update custom input scene on client
void force_update_custom_input_scene()

# Get resize viewport node
# @return resize viewport or null
GRSViewport get_gr_viewport()


# --- Signals

# On client connected
client_connected(device_id: String)

# On client disconnected
client_disconnected(device_id: String)

# On orientation of client's screen or viewport changed
client_viewport_orientation_changed(is_vertical: bool)

# On client's screen or viewport aspect ratio changed
client_viewport_aspect_ratio_changed(stream_aspect: float)

GRClient

# --- Properties

# Capture input only when containing control has focus
# type bool, default false
capture_on_focus

# Capture input only when stream image hovered
# type bool, default true
capture_when_hover

# Capture mouse pointer and touch events
# type bool, default true
capture_pointer

# Capture input
# type bool, default true
capture_input

# Type of connection
# type GRClient.ConnectionType, default CONNECTION_WiFi
connection_type

# Frequency of sending data to the server
# type int, default 60
target_send_fps

# Stretch mode of stream image
# type GRClient.StretchMode, default STRETCH_KEEP_ASPECT
stretch_mode

# Use texture filtering of stream image
# type bool, default true
texture_filtering

# Password
# type String, default ""
password

# ID of device
# type String, default 6 random digits and characters
device_id

# Sync viewport orientation with server
# type bool, default true
viewport_orientation_syncing

# Sync viewport aspect ratio with server
# type bool, default true
viewport_aspect_ratio_syncing

# Receive updated server settings
# type bool, default false
server_settings_syncing

# --- Methods

# Restore settings on server
void disable_overriding_server_settings()

# Get the current visible custom input scene
# @return: Custom input scene
Node get_custom_input_scene()

# Get server address
# @return server address
String get_address()

# Is connected to server
# @return true if connected to server
bool is_connected_to_host()

# Is stream active
# @return true if stream active
bool is_stream_active()

# Set server address to connect
# @ip: IP of server
# @return true if address is valid
bool set_address(ip: String)

# Set both server address and port
# @ip: IP of server
# @port: Port of server
# @return true if address is valid
bool set_address_port(ip: String, port: int)

# Set the control to show stream in
# @control_node: Control where stream will be shown
# @position_in_node: Position of stream in parent
void set_control_to_show_in(control_node: Control, position_in_node: int = 0)

# Set custom material for no signal screen
# @material: Custom material
void set_custom_no_signal_material(material: Material)

# Set custom horizontal texture for no signal screen
# @texture: Custom texture
void set_custom_no_signal_texture(texture: Texture)

# Set custom vertical texture for no signal screen
# @texture: Custom texture
void set_custom_no_signal_vertical_texture(texture: Texture)

# Override setting on server
# @setting: Which setting need to change
# @value: Value of setting
void set_server_setting(setting: GRdevice.TypesOfServerSettings, value: Variant)

# --- Signals

# On custom input scene added and becomes visible
custom_input_scene_added()

# On custom input scene removed
custom_input_scene_removed()

# On connection state changed
connection_state_changed(is_connected: bool)

# On stream state changed
stream_state_changed(state: GRClient.StreamState)

# On mouse mode changed on server
mouse_mode_changed(mouse_mode: Input.MouseMode)

# On received server settings from server
server_settings_received(settings: Dictionary)

# --- Enumerations

ConnectionType:
    CONNECTION_ADB = 1
    CONNECTION_WiFi = 0

StreamState:
    STREAM_NO_SIGNAL = 0
    STREAM_ACTIVE = 1
    STREAM_NO_IMAGE = 2

StretchMode:
    STRETCH_KEEP_ASPECT = 0
    STRETCH_FILL = 1

There is no need to describe other classes here

Custom Input Scenes

In custom input scenes you can use everything you want but to send InputEvent's from client to server you must emulate input. Or use the send_user_data() method and user_data_received signal for send and receive custom packets. Example:

# -- With InputEvent's

func _on_pressed():
    # Create event for pressed state
    var iea_p = InputEventAction.new()
    iea_p.pressed = true
    iea_p.action = "jump"
    # Create event for released state
    var iea_r = InputEventAction.new()
    iea_r.pressed = false
    iea_p.action = "jump"
    # Parse event to send it to the server
    Input.parse_input_event(iea_p)
    Input.parse_input_event(iea_r)

# -- With custom packets

# on first device
func _ready():
    GodotRemote.get_device().connect("user_data_received", self, "_on_user_data_received")

func _on_user_data_received(id, data):
    print("Received packet: %s, data: %s" % [id, data])

# on second device
func _on_button_pressed():
    GodotRemote.get_device().send_user_data("bg_color", color, false)

License

MIT license