summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/io/multiplayer_api.cpp39
-rw-r--r--core/io/multiplayer_api.h3
-rw-r--r--doc/classes/MultiplayerAPI.xml26
-rw-r--r--doc/classes/NetworkedMultiplayerPeer.xml3
-rw-r--r--doc/classes/Node.xml12
-rw-r--r--doc/classes/PanoramaSky.xml3
-rw-r--r--doc/classes/TileMap.xml47
-rw-r--r--doc/classes/Vector2.xml44
-rw-r--r--doc/classes/Vector3.xml42
-rw-r--r--editor/editor_settings.cpp2
-rw-r--r--main/main.cpp32
-rw-r--r--modules/enet/doc_classes/NetworkedMultiplayerENet.xml23
-rw-r--r--modules/enet/networked_multiplayer_enet.cpp85
-rw-r--r--modules/enet/networked_multiplayer_enet.h13
-rw-r--r--modules/freetype/SCsub3
-rw-r--r--platform/osx/os_osx.mm20
-rw-r--r--scene/3d/physics_body.cpp9
-rw-r--r--scene/3d/skeleton.cpp94
-rw-r--r--scene/3d/skeleton.h7
19 files changed, 362 insertions, 145 deletions
diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp
index 0ede7e87cb..456d29520f 100644
--- a/core/io/multiplayer_api.cpp
+++ b/core/io/multiplayer_api.cpp
@@ -76,7 +76,7 @@ Ref<NetworkedMultiplayerPeer> MultiplayerAPI::get_network_peer() const {
void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_packet_len) {
ERR_FAIL_COND(root_node == NULL);
- ERR_FAIL_COND(p_packet_len < 5);
+ ERR_FAIL_COND(p_packet_len < 1);
uint8_t packet_type = p_packet[0];
@@ -123,6 +123,11 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_
}
} break;
+
+ case NETWORK_COMMAND_RAW: {
+
+ _process_raw(p_from, p_packet, p_packet_len);
+ } break;
}
}
@@ -259,6 +264,8 @@ void MultiplayerAPI::_process_simplify_path(int p_from, const uint8_t *p_packet,
void MultiplayerAPI::_process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len) {
+ ERR_FAIL_COND(p_packet_len < 2);
+
String paths;
paths.parse_utf8((const char *)&p_packet[1], p_packet_len - 1);
@@ -648,6 +655,34 @@ void MultiplayerAPI::rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const
_send_rpc(p_node, p_peer_id, p_unreliable, true, p_property, &vptr, 1);
}
+Error MultiplayerAPI::send_bytes(PoolVector<uint8_t> p_data, int p_to) {
+
+ ERR_FAIL_COND_V(p_data.size() < 1, ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(!network_peer.is_valid(), ERR_UNCONFIGURED);
+ ERR_FAIL_COND_V(network_peer->get_connection_status() != NetworkedMultiplayerPeer::CONNECTION_CONNECTED, ERR_UNCONFIGURED);
+
+ MAKE_ROOM(p_data.size() + 1);
+ PoolVector<uint8_t>::Read r = p_data.read();
+ packet_cache[0] = NETWORK_COMMAND_RAW;
+ memcpy(&packet_cache[1], &r[0], p_data.size());
+ network_peer->set_target_peer(p_to);
+ return network_peer->put_packet(packet_cache.ptr(), p_data.size() + 1);
+}
+
+void MultiplayerAPI::_process_raw(int p_from, const uint8_t *p_packet, int p_packet_len) {
+
+ ERR_FAIL_COND(p_packet_len < 2);
+
+ PoolVector<uint8_t> out;
+ int len = p_packet_len - 1;
+ out.resize(len);
+ {
+ PoolVector<uint8_t>::Write w = out.write();
+ memcpy(&w[0], &p_packet[1], len);
+ }
+ emit_signal("network_peer_packet", p_from, out);
+}
+
int MultiplayerAPI::get_network_unique_id() const {
ERR_FAIL_COND_V(!network_peer.is_valid(), 0);
@@ -686,6 +721,7 @@ Vector<int> MultiplayerAPI::get_network_connected_peers() const {
void MultiplayerAPI::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_root_node", "node"), &MultiplayerAPI::set_root_node);
+ ClassDB::bind_method(D_METHOD("send_bytes", "bytes", "id"), &MultiplayerAPI::send_bytes, DEFVAL(NetworkedMultiplayerPeer::TARGET_PEER_BROADCAST));
ClassDB::bind_method(D_METHOD("has_network_peer"), &MultiplayerAPI::has_network_peer);
ClassDB::bind_method(D_METHOD("get_network_peer"), &MultiplayerAPI::get_network_peer);
ClassDB::bind_method(D_METHOD("get_network_unique_id"), &MultiplayerAPI::get_network_unique_id);
@@ -708,6 +744,7 @@ void MultiplayerAPI::_bind_methods() {
ADD_SIGNAL(MethodInfo("network_peer_connected", PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL(MethodInfo("network_peer_disconnected", PropertyInfo(Variant::INT, "id")));
+ ADD_SIGNAL(MethodInfo("network_peer_packet", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::POOL_BYTE_ARRAY, "packet")));
ADD_SIGNAL(MethodInfo("connected_to_server"));
ADD_SIGNAL(MethodInfo("connection_failed"));
ADD_SIGNAL(MethodInfo("server_disconnected"));
diff --git a/core/io/multiplayer_api.h b/core/io/multiplayer_api.h
index cc60890ced..25f445004d 100644
--- a/core/io/multiplayer_api.h
+++ b/core/io/multiplayer_api.h
@@ -43,6 +43,7 @@ protected:
Node *_process_get_node(int p_from, const uint8_t *p_packet, int p_packet_len);
void _process_rpc(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset);
void _process_rset(Node *p_node, const StringName &p_name, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset);
+ void _process_raw(int p_from, const uint8_t *p_packet, int p_packet_len);
void _send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p_set, const StringName &p_name, const Variant **p_arg, int p_argcount);
bool _send_confirm_path(NodePath p_path, PathSentCache *psc, int p_from);
@@ -53,6 +54,7 @@ public:
NETWORK_COMMAND_REMOTE_SET,
NETWORK_COMMAND_SIMPLIFY_PATH,
NETWORK_COMMAND_CONFIRM_PATH,
+ NETWORK_COMMAND_RAW,
};
void poll();
@@ -60,6 +62,7 @@ public:
void set_root_node(Node *p_node);
void set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_peer);
Ref<NetworkedMultiplayerPeer> get_network_peer() const;
+ Error send_bytes(PoolVector<uint8_t> p_data, int p_to = NetworkedMultiplayerPeer::TARGET_PEER_BROADCAST);
// Called by Node.rpc
void rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const StringName &p_method, const Variant **p_arg, int p_argcount);
diff --git a/doc/classes/MultiplayerAPI.xml b/doc/classes/MultiplayerAPI.xml
index b2ed712554..f6950d0fbc 100644
--- a/doc/classes/MultiplayerAPI.xml
+++ b/doc/classes/MultiplayerAPI.xml
@@ -61,10 +61,21 @@
</return>
<description>
Method used for polling the MultiplayerAPI.
- You only need to worry about this if you are using [memeber Node.custom_multplayer] override.
+ You only need to worry about this if you are using [member Node.custom_multplayer] override.
SceneTree will poll the default MultiplayerAPI for you.
</description>
</method>
+ <method name="send_bytes">
+ <return type="int" enum="Error">
+ </return>
+ <argument index="0" name="bytes" type="PoolByteArray">
+ </argument>
+ <argument index="1" name="id" type="int" default="0">
+ </argument>
+ <description>
+ Sends the given raw [code]bytes[/code] to a specific peer identified by [code]id[/code] (see [method NetworkedMultiplayerPeer.set_target_peer]). Default ID is [code]0[/code], i.e. broadcast to all peers.
+ </description>
+ </method>
<method name="set_root_node">
<return type="void">
</return>
@@ -78,7 +89,7 @@
</methods>
<members>
<member name="network_peer" type="NetworkedMultiplayerPeer" setter="set_network_peer" getter="get_network_peer">
- The peer object to handle the RPC system (effectively enabling networking when set). Depending on the peer itself, the MultiplayerAPI will become a network server (check with [method is_network_server()]) and will set root node's network mode to master (see NETWORK_MODE_* constants in [Node]), or it will become a regular peer with root node set to slave. All child nodes are set to inherit the network mode by default. Handling of networking-related events (connection, disconnection, new clients) is done by connecting to MultiplayerAPI's signals.
+ The peer object to handle the RPC system (effectively enabling networking when set). Depending on the peer itself, the MultiplayerAPI will become a network server (check with [method is_network_server]) and will set root node's network mode to master (see NETWORK_MODE_* constants in [Node]), or it will become a regular peer with root node set to slave. All child nodes are set to inherit the network mode by default. Handling of networking-related events (connection, disconnection, new clients) is done by connecting to MultiplayerAPI's signals.
</member>
<member name="refuse_new_network_connections" type="bool" setter="set_refuse_new_network_connections" getter="is_refusing_new_network_connections">
If [code]true[/code] the MultiplayerAPI's [member network_peer] refuses new incoming connections.
@@ -109,9 +120,18 @@
Emitted whenever this MultiplayerAPI's [member network_peer] disconnects from a peer. Clients get notified when other clients disconnect from the same server.
</description>
</signal>
+ <signal name="network_peer_packet">
+ <argument index="0" name="id" type="int">
+ </argument>
+ <argument index="1" name="packet" type="PoolByteArray">
+ </argument>
+ <description>
+ Emitted whenever this MultiplayerAPI's [member network_peer] receive a [code]packet[/code] with custom data (see [method send_bytes]). ID is the peer ID of the peer that sent the packet.
+ </description>
+ </signal>
<signal name="server_disconnected">
<description>
- Emitted whenever this MultiplayerAPI's [member network_peer] disconnected from server. Only emitted on clients.
+ Emitted whenever this MultiplayerAPI's [member network_peer] disconnects from server. Only emitted on clients.
</description>
</signal>
</signals>
diff --git a/doc/classes/NetworkedMultiplayerPeer.xml b/doc/classes/NetworkedMultiplayerPeer.xml
index 71614c5f76..2780334384 100644
--- a/doc/classes/NetworkedMultiplayerPeer.xml
+++ b/doc/classes/NetworkedMultiplayerPeer.xml
@@ -46,7 +46,8 @@
<argument index="0" name="id" type="int">
</argument>
<description>
- The peer to which packets will be sent. Default value: [code]0[/code].
+ Sets the peer to which packets will be sent.
+ The [code]id[/code] can be one of: [code]TARGET_PEER_BROADCAST[/code] to send to all connected peers, [code]TARGET_PEER_SERVER[/code] to send to the peer acting as server, a valid peer ID to send to that specific peer, a negative peer ID to send to all peers except that one. Default: [code]TARGET_PEER_BROADCAST[/code]
</description>
</method>
</methods>
diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml
index c11b8aacaa..05ac6b1c0e 100644
--- a/doc/classes/Node.xml
+++ b/doc/classes/Node.xml
@@ -586,7 +586,7 @@
<argument index="1" name="method" type="String">
</argument>
<description>
- Sends a [method rpc] to a specific peer identified by [code]peer_id[/code]. Returns an empty [Variant].
+ Sends a [method rpc] to a specific peer identified by [code]peer_id[/code] (see [method NetworkedMultiplayerPeer.set_target_peer]). Returns an empty [Variant].
</description>
</method>
<method name="rpc_unreliable" qualifiers="vararg">
@@ -606,7 +606,7 @@
<argument index="1" name="method" type="String">
</argument>
<description>
- Sends a [method rpc] to a specific peer identified by [code]peer_id[/code] using an unreliable protocol. Returns an empty [Variant].
+ Sends a [method rpc] to a specific peer identified by [code]peer_id[/code] using an unreliable protocol (see [method NetworkedMultiplayerPeer.set_target_peer]). Returns an empty [Variant].
</description>
</method>
<method name="rset">
@@ -641,7 +641,7 @@
<argument index="2" name="value" type="Variant">
</argument>
<description>
- Remotely changes the property's value on a specific peer identified by [code]peer_id[/code].
+ Remotely changes the property's value on a specific peer identified by [code]peer_id[/code] (see [method NetworkedMultiplayerPeer.set_target_peer]).
</description>
</method>
<method name="rset_unreliable">
@@ -665,7 +665,7 @@
<argument index="2" name="value" type="Variant">
</argument>
<description>
- Remotely changes property's value on a specific peer identified by [code]peer_id[/code] using an unreliable protocol.
+ Remotely changes property's value on a specific peer identified by [code]peer_id[/code] using an unreliable protocol (see [method NetworkedMultiplayerPeer.set_target_peer]).
</description>
</method>
<method name="set_display_folded">
@@ -703,7 +703,7 @@
<argument index="0" name="enable" type="bool">
</argument>
<description>
- Enables or disables internal physics for this node. Internal physics processing happens in isolation from the normal [method]_physics_process[/code] calls and is used by some nodes internally to guarantee proper functioning even if the node is paused or physics processing is disabled for scripting ([method set_physics_process]). Only useful for advanced uses to manipulate built-in nodes behaviour.
+ Enables or disables internal physics for this node. Internal physics processing happens in isolation from the normal [method _physics_process] calls and is used by some nodes internally to guarantee proper functioning even if the node is paused or physics processing is disabled for scripting ([method set_physics_process]). Only useful for advanced uses to manipulate built-in nodes behaviour.
</description>
</method>
<method name="set_process">
@@ -730,7 +730,7 @@
<argument index="0" name="enable" type="bool">
</argument>
<description>
- Enables or disabled internal processing for this node. Internal processing happens in isolation from the normal [method]_process[/code] calls and is used by some nodes internally to guarantee proper functioning even if the node is paused or processing is disabled for scripting ([method set_process]). Only useful for advanced uses to manipulate built-in nodes behaviour.
+ Enables or disabled internal processing for this node. Internal processing happens in isolation from the normal [method _process] calls and is used by some nodes internally to guarantee proper functioning even if the node is paused or processing is disabled for scripting ([method set_process]). Only useful for advanced uses to manipulate built-in nodes behaviour.
</description>
</method>
<method name="set_process_unhandled_input">
diff --git a/doc/classes/PanoramaSky.xml b/doc/classes/PanoramaSky.xml
index eb288d13be..402e65c573 100644
--- a/doc/classes/PanoramaSky.xml
+++ b/doc/classes/PanoramaSky.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="PanoramaSky" inherits="Sky" category="Core" version="3.1">
<brief_description>
+ A type of [Sky] used to draw a background texture.
</brief_description>
<description>
+ A resource referenced in an [Environment] that is used to draw a background. The Panorama sky functions similar to skyboxes in other engines except it uses a equirectangular sky map instead of a cube map.
</description>
<tutorials>
</tutorials>
@@ -12,6 +14,7 @@
</methods>
<members>
<member name="panorama" type="Texture" setter="set_panorama" getter="get_panorama">
+ [Texture] to be applied to the PanoramaSky.
</member>
</members>
<constants>
diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml
index ec67370c79..775fef4fb7 100644
--- a/doc/classes/TileMap.xml
+++ b/doc/classes/TileMap.xml
@@ -16,14 +16,14 @@
<return type="void">
</return>
<description>
- Clear all cells.
+ Clears all cells.
</description>
</method>
<method name="fix_invalid_tiles">
<return type="void">
</return>
<description>
- Clear cells that does not exist in the tileset.
+ Clears cells that do not exist in the tileset.
</description>
</method>
<method name="get_cell" qualifiers="const">
@@ -34,7 +34,7 @@
<argument index="1" name="y" type="int">
</argument>
<description>
- Return the tile index of the referenced cell.
+ Returns the tile index of the given cell.
</description>
</method>
<method name="get_cellv" qualifiers="const">
@@ -43,7 +43,7 @@
<argument index="0" name="position" type="Vector2">
</argument>
<description>
- Return the tile index of the cell referenced by a Vector2.
+ Returns the tile index of the cell given by a Vector2.
</description>
</method>
<method name="get_collision_layer_bit" qualifiers="const">
@@ -52,6 +52,7 @@
<argument index="0" name="bit" type="int">
</argument>
<description>
+ Returns [code]true[/code] if the given collision layer bit is set.
</description>
</method>
<method name="get_collision_mask_bit" qualifiers="const">
@@ -60,13 +61,14 @@
<argument index="0" name="bit" type="int">
</argument>
<description>
+ Returns [code]true[/code] if the given collision mask bit is set.
</description>
</method>
<method name="get_used_cells" qualifiers="const">
<return type="Array">
</return>
<description>
- Return an array of all cells containing a tile from the tileset (i.e. a tile index different from -1).
+ Returns an array of all cells containing a tile from the tileset (i.e. a tile index different from [code]-1[/code]).
</description>
</method>
<method name="get_used_cells_by_id" qualifiers="const">
@@ -75,12 +77,14 @@
<argument index="0" name="id" type="int">
</argument>
<description>
+ Returns an array of all cells with the given tile id.
</description>
</method>
<method name="get_used_rect">
<return type="Rect2">
</return>
<description>
+ Returns a rectangle enclosing the used (non-empty) tiles of the map.
</description>
</method>
<method name="is_cell_transposed" qualifiers="const">
@@ -91,7 +95,7 @@
<argument index="1" name="y" type="int">
</argument>
<description>
- Return whether the referenced cell is transposed, i.e. the X and Y axes are swapped (mirroring with regard to the (1,1) vector).
+ Returns [code]true[/code] if the given cell is transposed, i.e. the x and y axes are swapped.
</description>
</method>
<method name="is_cell_x_flipped" qualifiers="const">
@@ -102,7 +106,7 @@
<argument index="1" name="y" type="int">
</argument>
<description>
- Return whether the referenced cell is flipped over the X axis.
+ Returns [code]true[/code] if the given cell is flipped in the x axis.
</description>
</method>
<method name="is_cell_y_flipped" qualifiers="const">
@@ -113,7 +117,7 @@
<argument index="1" name="y" type="int">
</argument>
<description>
- Return whether the referenced cell is flipped over the Y axis.
+ Returns [code]true[/code] if the given cell is flipped in the y axis.
</description>
</method>
<method name="map_to_world" qualifiers="const">
@@ -124,8 +128,8 @@
<argument index="1" name="ignore_half_ofs" type="bool" default="false">
</argument>
<description>
- Return the absolute world position corresponding to the tilemap (grid-based) coordinates given as an argument.
- Optionally, the tilemap's potential half offset can be ignored.
+ Returns the global position corresponding to the given tilemap (grid-based) coordinates.
+ Optionally, the tilemap's half offset can be ignored.
</description>
</method>
<method name="set_cell">
@@ -146,9 +150,9 @@
<argument index="6" name="autotile_coord" type="Vector2" default="Vector2( 0, 0 )">
</argument>
<description>
- Set the tile index for the cell referenced by its grid-based X and Y coordinates.
- A tile index of -1 clears the cell.
- Optionally, the tile can also be flipped over the X and Y coordinates, transposed, or be given autotile coordinates.
+ Sets the tile index for the cell given by a Vector2.
+ An index of [code]-1[/code] clears the cell.
+ Optionally, the tile can also be flipped, transposed, or given autotile coordinates.
</description>
</method>
<method name="set_cellv">
@@ -165,9 +169,9 @@
<argument index="4" name="transpose" type="bool" default="false">
</argument>
<description>
- Set the tile index for the cell referenced by a Vector2 of grid-based coordinates.
- A tile index of -1 clears the cell.
- Optionally, the tile can also be flipped over the X and Y axes or transposed.
+ Sets the tile index for the given cell.
+ An index of [code]-1[/code] clears the cell.
+ Optionally, the tile can also be flipped or transposed.
</description>
</method>
<method name="set_collision_layer_bit">
@@ -178,7 +182,7 @@
<argument index="1" name="value" type="bool">
</argument>
<description>
- Set any collision layer to be [code]true[/code] or [code]false[/code].
+ Sets the given collision layer bit.
</description>
</method>
<method name="set_collision_mask_bit">
@@ -189,6 +193,7 @@
<argument index="1" name="value" type="bool">
</argument>
<description>
+ Sets the given collision mask bit.
</description>
</method>
<method name="update_bitmask_area">
@@ -197,7 +202,7 @@
<argument index="0" name="position" type="Vector2">
</argument>
<description>
- Applies autotiling rules to the cell (and its adjacent cells) referenced by its grid-based X and Y coordinates.
+ Applies autotiling rules to the cell (and its adjacent cells) referenced by its grid-based x and y coordinates.
</description>
</method>
<method name="update_bitmask_region">
@@ -208,8 +213,8 @@
<argument index="1" name="end" type="Vector2" default="Vector2( 0, 0 )">
</argument>
<description>
- Applies autotiling rules to the cells in the given region (specified by grid-based X and Y coordinates).
- Calling with invalid (or missing) parameters applies autotiling rules for the entire TileMap.
+ Applies autotiling rules to the cells in the given region (specified by grid-based x and y coordinates).
+ Calling with invalid (or missing) parameters applies autotiling rules for the entire tilemap.
</description>
</method>
<method name="world_to_map" qualifiers="const">
@@ -218,7 +223,7 @@
<argument index="0" name="world_position" type="Vector2">
</argument>
<description>
- Return the tilemap (grid-based) coordinates corresponding to the absolute world position given as an argument.
+ Returns the tilemap (grid-based) coordinatescorresponding to the given global position.
</description>
</method>
</methods>
diff --git a/doc/classes/Vector2.xml b/doc/classes/Vector2.xml
index 66563dc5a4..ec92dcf900 100644
--- a/doc/classes/Vector2.xml
+++ b/doc/classes/Vector2.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Vector2" category="Built-In Types" version="3.1">
<brief_description>
- Vector used for 2D Math.
+ Vector used for 2D math.
</brief_description>
<description>
- 2-element structure that can be used to represent positions in 2d-space, or any other pair of numeric values.
+ 2-element structure that can be used to represent positions in 2d space or any other pair of numeric values.
</description>
<tutorials>
http://docs.godotengine.org/en/3.0/tutorials/math/index.html
@@ -34,8 +34,8 @@
<return type="float">
</return>
<description>
- Returns the result of atan2 when called with the Vector's x and y as parameters (Math::atan2(x,y)).
- Be aware that it therefore returns an angle oriented clockwise with regard to the (0, 1) unit vector, and not an angle oriented counter-clockwise with regard to the (1, 0) unit vector (which would be the typical trigonometric representation of the angle when calling Math::atan2(y,x)).
+ Returns the vector's angle in radians with respect to the x-axis, or [code](1, 0)[/code] vector.
+ Equivalent to the result of atan2 when called with the vector's x and y as parameters: [code]atan2(x, y)[/code].
</description>
</method>
<method name="angle_to">
@@ -60,7 +60,7 @@
<return type="float">
</return>
<description>
- Returns the ratio of X to Y.
+ Returns the ratio of x to y.
</description>
</method>
<method name="bounce">
@@ -69,7 +69,7 @@
<argument index="0" name="n" type="Vector2">
</argument>
<description>
- Bounce returns the vector "bounced off" from the given plane, specified by its normal vector.
+ Returns the vector "bounced off" from a plane defined by the given normal.
</description>
</method>
<method name="ceil">
@@ -93,7 +93,7 @@
<argument index="0" name="with" type="Vector2">
</argument>
<description>
- Returns the 2-dimensional analog of the cross product with the given Vector2.
+ Returns the 2 dimensional analog of the cross product with the given vector.
</description>
</method>
<method name="cubic_interpolate">
@@ -108,7 +108,7 @@
<argument index="3" name="t" type="float">
</argument>
<description>
- Cubicly interpolates between this Vector and "b", using "pre_a" and "post_b" as handles, and returning the result at position "t". "t" should be a float of 0.0-1.0, a percentage of how far along the interpolation is.
+ Cubicly interpolates between this vector and [code]b[/code] using [code]pre_a[/code] and [code]post_b[/code] as handles, and returns the result at position [code]t[/code]. [code]t[/code] is in the range of [code]0.0 - 1.0[/code], or a percentage of how far along the interpolation is.
</description>
</method>
<method name="distance_squared_to">
@@ -117,7 +117,7 @@
<argument index="0" name="to" type="Vector2">
</argument>
<description>
- Returns the squared distance to vector "b". Prefer this function over "distance_to" if you need to sort vectors or need the squared distance for some formula.
+ Returns the squared distance to vector [code]b[/code]. Prefer this function over [method distance_to] if you need to sort vectors or need the squared distance for some formula.
</description>
</method>
<method name="distance_to">
@@ -126,7 +126,7 @@
<argument index="0" name="to" type="Vector2">
</argument>
<description>
- Returns the distance to vector "b".
+ Returns the distance to vector [code]b[/code].
</description>
</method>
<method name="dot">
@@ -135,7 +135,7 @@
<argument index="0" name="with" type="Vector2">
</argument>
<description>
- Returns the dot product with vector "b".
+ Returns the dot product with vector [code]b[/code].
</description>
</method>
<method name="floor">
@@ -149,21 +149,21 @@
<return type="bool">
</return>
<description>
- Returns whether the vector is normalized or not.
+ Returns [code]true[/code] if the vector is normalized.
</description>
</method>
<method name="length">
<return type="float">
</return>
<description>
- Returns the length of the vector.
+ Returns the vector's length.
</description>
</method>
<method name="length_squared">
<return type="float">
</return>
<description>
- Returns the squared length of the vector. Prefer this function over "length" if you need to sort vectors or need the squared length for some formula.
+ Returns the vector's length squared. Prefer this function over [member length] if you need to sort vectors or need the squared length for some formula.
</description>
</method>
<method name="linear_interpolate">
@@ -174,14 +174,14 @@
<argument index="1" name="t" type="float">
</argument>
<description>
- Returns the result of the linear interpolation between this vector and "b", by amount "t". "t" should be a float of 0.0-1.0, a percentage of how far along the interpolation is.
+ Returns the result of the linear interpolation between this vector and [code]b[/code] by amount [code]t[/code]. [code]t[/code] is in the range of [code]0.0 - 1.0[/code], a percentage of how far along the interpolation is.
</description>
</method>
<method name="normalized">
<return type="Vector2">
</return>
<description>
- Returns a normalized vector to unit length.
+ Returns the vector scaled to unit length. Equivalent to [code]v / v.length()[/code].
</description>
</method>
<method name="reflect">
@@ -190,7 +190,7 @@
<argument index="0" name="n" type="Vector2">
</argument>
<description>
- Reflects the vector along the given plane, specified by its normal vector.
+ Returns the vector reflected from a plane defined by the given normal.
</description>
</method>
<method name="rotated">
@@ -199,7 +199,7 @@
<argument index="0" name="phi" type="float">
</argument>
<description>
- Rotates the vector by "phi" radians.
+ Returns the vector rotated by [code]phi[/code] radians.
</description>
</method>
<method name="round">
@@ -214,7 +214,7 @@
<argument index="0" name="n" type="Vector2">
</argument>
<description>
- Slide returns the component of the vector along the given plane, specified by its normal vector.
+ Returns the component of the vector along a plane defined by the given normal.
</description>
</method>
<method name="snapped">
@@ -223,7 +223,7 @@
<argument index="0" name="by" type="Vector2">
</argument>
<description>
- Snaps the vector to a grid with the given size.
+ Returns the vector snapped to a grid with the given size.
</description>
</method>
<method name="tangent">
@@ -236,10 +236,10 @@
</methods>
<members>
<member name="x" type="float" setter="" getter="">
- X component of the vector.
+ The vector's x component.
</member>
<member name="y" type="float" setter="" getter="">
- Y component of the vector.
+ The vector's y component.
</member>
</members>
<constants>
diff --git a/doc/classes/Vector3.xml b/doc/classes/Vector3.xml
index 0ffb5603c7..a5fc62b6f0 100644
--- a/doc/classes/Vector3.xml
+++ b/doc/classes/Vector3.xml
@@ -38,7 +38,7 @@
<argument index="0" name="to" type="Vector3">
</argument>
<description>
- Returns the vector's minimum angle to the vector [code]to[/code].
+ Returns the minimum angle to the given vector.
</description>
</method>
<method name="bounce">
@@ -47,7 +47,7 @@
<argument index="0" name="n" type="Vector3">
</argument>
<description>
- Bounce returns the vector "bounced off" from the given plane, specified by its normal vector.
+ Returns the vector "bounced off" from a plane defined by the given normal.
</description>
</method>
<method name="ceil">
@@ -87,7 +87,7 @@
<argument index="0" name="b" type="Vector3">
</argument>
<description>
- Returns the squared distance to [code]b[/code]. Prefer this function over distance_to if you need to sort vectors or need the squared distance for some formula.
+ Returns the squared distance to [code]b[/code]. Prefer this function over [method distance_to] if you need to sort vectors or need the squared distance for some formula.
</description>
</method>
<method name="distance_to">
@@ -96,7 +96,7 @@
<argument index="0" name="b" type="Vector3">
</argument>
<description>
- Returns the distance to b.
+ Returns the distance to [code]b[/code].
</description>
</method>
<method name="dot">
@@ -105,7 +105,7 @@
<argument index="0" name="b" type="Vector3">
</argument>
<description>
- Returns the dot product with b.
+ Returns the dot product with [code]b[/code].
</description>
</method>
<method name="floor">
@@ -119,28 +119,28 @@
<return type="Vector3">
</return>
<description>
- Returns the inverse of the vector. This is the same as Vector3( 1.0 / v.x, 1.0 / v.y, 1.0 / v.z )
+ Returns the inverse of the vector. This is the same as [code]Vector3( 1.0 / v.x, 1.0 / v.y, 1.0 / v.z )[/code].
</description>
</method>
<method name="is_normalized">
<return type="bool">
</return>
<description>
- Returns whether the vector is normalized or not.
+ Returns [code]true[/code] if the vector is normalized.
</description>
</method>
<method name="length">
<return type="float">
</return>
<description>
- Returns the length of the vector.
+ Returns the vector's length.
</description>
</method>
<method name="length_squared">
<return type="float">
</return>
<description>
- Returns the length of the vector, squared. Prefer this function over "length" if you need to sort vectors or need the squared length for some formula.
+ Returns the vector's length squared. Prefer this function over [method length] if you need to sort vectors or need the squared length for some formula.
</description>
</method>
<method name="linear_interpolate">
@@ -151,28 +151,28 @@
<argument index="1" name="t" type="float">
</argument>
<description>
- Linearly interpolates the vector to a given one (b), by the given amount (t). (t) should be a float of 0.0-1.0, a percentage of how far along the interpolation is.
+ Returns the result of the linear interpolation between this vector and [code]b[/code] by amount [code]t[/code]. [code]t[/code] is in the range of [code]0.0 - 1.0[/code], a percentage of how far along the interpolation is.
</description>
</method>
<method name="max_axis">
<return type="int">
</return>
<description>
- Returns AXIS_X, AXIS_Y or AXIS_Z depending on which axis is the largest.
+ Returns the axis of the vector's largest value. See [code]AXIS_*[/code] constants.
</description>
</method>
<method name="min_axis">
<return type="int">
</return>
<description>
- Returns AXIS_X, AXIS_Y or AXIS_Z depending on which axis is the smallest.
+ Returns the axis of the vector's smallest value. See [code]AXIS_*[/code] constants.
</description>
</method>
<method name="normalized">
<return type="Vector3">
</return>
<description>
- Returns a copy of the normalized vector to unit length. This is the same as v / v.length().
+ Returns the vector scaled to unit length. Equivalent to [code]v / v.length()[/code].
</description>
</method>
<method name="outer">
@@ -181,7 +181,7 @@
<argument index="0" name="b" type="Vector3">
</argument>
<description>
- Returns the outer product with b.
+ Returns the outer product with [code]b[/code].
</description>
</method>
<method name="reflect">
@@ -190,7 +190,7 @@
<argument index="0" name="n" type="Vector3">
</argument>
<description>
- Reflects the vector along the given plane, specified by its normal vector.
+ Returns the vector reflected from a plane defined by the given normal.
</description>
</method>
<method name="rotated">
@@ -201,7 +201,7 @@
<argument index="1" name="phi" type="float">
</argument>
<description>
- Rotates the vector around some axis by phi radians. The axis must be a normalized vector.
+ Rotates the vector around a given axis by [code]phi[/code] radians. The axis must be a normalized vector.
</description>
</method>
<method name="round">
@@ -216,7 +216,7 @@
<argument index="0" name="n" type="Vector3">
</argument>
<description>
- Slide returns the component of the vector along the given plane, specified by its normal vector.
+ Returns the component of the vector along a plane defined by the given normal.
</description>
</method>
<method name="snapped">
@@ -238,18 +238,18 @@
</methods>
<members>
<member name="x" type="float" setter="" getter="">
- X component of the vector.
+ The vector's x component.
</member>
<member name="y" type="float" setter="" getter="">
- Y component of the vector.
+ The vector's y component.
</member>
<member name="z" type="float" setter="" getter="">
- Z component of the vector.
+ The vector's z component.
</member>
</members>
<constants>
<constant name="AXIS_X" value="0">
- Enumerated value for the X axis. Returned by functions like max_axis or min_axis.
+ Enumerated value for the X axis. Returned by [method max_axis] and [method min_axis].
</constant>
<constant name="AXIS_Y" value="1">
Enumerated value for the Y axis.
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 12f5f3f9be..7aca92e3ab 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -299,7 +299,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("interface/editor/main_font", "");
hints["interface/editor/main_font"] = PropertyInfo(Variant::STRING, "interface/editor/main_font", PROPERTY_HINT_GLOBAL_FILE, "*.ttf,*.otf", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
_initial_set("interface/editor/main_font_bold", "");
- hints["interface/editor/main_font_bold"] = PropertyInfo(Variant::STRING, "interface/editor/main_bold_font", PROPERTY_HINT_GLOBAL_FILE, "*.ttf,*.otf", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
+ hints["interface/editor/main_font_bold"] = PropertyInfo(Variant::STRING, "interface/editor/main_font_bold", PROPERTY_HINT_GLOBAL_FILE, "*.ttf,*.otf", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
_initial_set("interface/editor/code_font", "");
hints["interface/editor/code_font"] = PropertyInfo(Variant::STRING, "interface/editor/code_font", PROPERTY_HINT_GLOBAL_FILE, "*.ttf,*.otf", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
_initial_set("interface/editor/dim_editor_on_dialog_popup", true);
diff --git a/main/main.cpp b/main/main.cpp
index 36d27f19ec..5836c9c739 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -337,7 +337,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
String video_driver = "";
String audio_driver = "";
- String game_path;
+ String project_path = ".";
bool upwards = false;
String debug_mode;
String debug_host;
@@ -553,7 +553,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
if (OS::get_singleton()->set_cwd(p) == OK) {
//nothing
} else {
- game_path = I->next()->get(); //use game_path instead
+ project_path = I->next()->get(); //use project_path instead
}
N = I->next()->next();
} else {
@@ -576,7 +576,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
if (OS::get_singleton()->set_cwd(path) == OK) {
// path already specified, don't override
} else {
- game_path = path;
+ project_path = path;
}
#ifdef TOOLS_ENABLED
editor = true;
@@ -672,38 +672,20 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
} else if (I->get() == "--disable-crash-handler") {
OS::get_singleton()->disable_crash_handler();
} else {
-
- //test for game path
- bool gpfound = false;
-
- if (!I->get().begins_with("-") && game_path == "") {
- DirAccess *da = DirAccess::open(I->get());
- if (da != NULL) {
- game_path = I->get();
- gpfound = true;
- memdelete(da);
- }
- }
-
- if (!gpfound) {
- main_args.push_back(I->get());
- }
+ main_args.push_back(I->get());
}
I = N;
}
- if (game_path.empty()) {
- game_path = ".";
- }
- if (globals->setup(game_path, main_pack, upwards) == OK) {
+ if (globals->setup(project_path, main_pack, upwards) == OK) {
found_project = true;
} else {
#ifdef TOOLS_ENABLED
editor = false;
#else
- OS::get_singleton()->print("Error: Could not load game path '%s'.\n", game_path.ascii().get_data());
+ OS::get_singleton()->print("Error: Could not load game path '%s'.\n", project_path.ascii().get_data());
goto error;
#endif
@@ -994,7 +976,7 @@ error:
video_driver = "";
audio_driver = "";
- game_path = "";
+ project_path = "";
args.clear();
main_args.clear();
diff --git a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
index 4b2a9df8c4..d5fd4bff09 100644
--- a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
+++ b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
@@ -65,6 +65,20 @@
Disconnect the given peer. If "now" is set to true, the connection will be closed immediately without flushing queued messages.
</description>
</method>
+ <method name="get_last_packet_channel" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ Returns the channel of the last packet fetched via [method PacketPeer.get_packet]
+ </description>
+ </method>
+ <method name="get_packet_channel" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ Returns the channel of the next packet that will be retrieved via [method PacketPeer.get_packet_peer]
+ </description>
+ </method>
<method name="get_peer_address" qualifiers="const">
<return type="String">
</return>
@@ -94,9 +108,18 @@
</method>
</methods>
<members>
+ <member name="always_ordered" type="bool" setter="set_always_ordered" getter="is_always_ordered">
+ Always use [code]TRANSFER_MODE_ORDERED[/code] in place of [code]TRANSFER_MODE_UNRELIABLE[/code]. This is the only way to use ordering with the RPC system.
+ </member>
+ <member name="channel_count" type="int" setter="set_channel_count" getter="get_channel_count">
+ The number of channels to be used by ENet. Default: [code]3[/code]. Channels are used to separate different kinds of data. In realiable or ordered mode, for example, the packet delivery order is ensured on a per channel basis.
+ </member>
<member name="compression_mode" type="int" setter="set_compression_mode" getter="get_compression_mode" enum="NetworkedMultiplayerENet.CompressionMode">
The compression method used for network packets. Default is no compression. These have different tradeoffs of compression speed versus bandwidth, you may need to test which one works best for your use case if you use compression at all.
</member>
+ <member name="transfer_channel" type="int" setter="set_transfer_channel" getter="get_transfer_channel">
+ Set the default channel to be used to transfer data. By default this value is [code]-1[/code] which means that ENet will only use 2 channels, one for reliable and one for unreliable packets. Channel [code]0[/code] is reserved, and cannot be used. Setting this member to any value between [code]0[/code] and [member channel_count] (excluded) will force ENet to use that channel for sending data.
+ </member>
</members>
<constants>
<constant name="COMPRESS_NONE" value="0" enum="CompressionMode">
diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/networked_multiplayer_enet.cpp
index e948df2742..88768829d7 100644
--- a/modules/enet/networked_multiplayer_enet.cpp
+++ b/modules/enet/networked_multiplayer_enet.cpp
@@ -55,6 +55,22 @@ int NetworkedMultiplayerENet::get_packet_peer() const {
return incoming_packets.front()->get().from;
}
+int NetworkedMultiplayerENet::get_packet_channel() const {
+
+ ERR_FAIL_COND_V(!active, -1);
+ ERR_FAIL_COND_V(incoming_packets.size() == 0, -1);
+
+ return incoming_packets.front()->get().channel;
+}
+
+int NetworkedMultiplayerENet::get_last_packet_channel() const {
+
+ ERR_FAIL_COND_V(!active, -1);
+ ERR_FAIL_COND_V(!current_packet.packet, -1);
+
+ return current_packet.channel;
+}
+
Error NetworkedMultiplayerENet::create_server(int p_port, int p_max_clients, int p_in_bandwidth, int p_out_bandwidth) {
ERR_FAIL_COND_V(active, ERR_ALREADY_IN_USE);
@@ -83,7 +99,7 @@ Error NetworkedMultiplayerENet::create_server(int p_port, int p_max_clients, int
host = enet_host_create(&address /* the address to bind the server host to */,
p_max_clients /* allow up to 32 clients and/or outgoing connections */,
- SYSCH_MAX /* allow up to SYSCH_MAX channels to be used */,
+ channel_count /* allow up to channel_count to be used */,
p_in_bandwidth /* limit incoming bandwith if > 0 */,
p_out_bandwidth /* limit outgoing bandwith if > 0 */);
@@ -127,13 +143,13 @@ Error NetworkedMultiplayerENet::create_client(const String &p_address, int p_por
host = enet_host_create(&c_client /* create a client host */,
1 /* only allow 1 outgoing connection */,
- SYSCH_MAX /* allow up to SYSCH_MAX channels to be used */,
+ channel_count /* allow up to channel_count to be used */,
p_in_bandwidth /* limit incoming bandwith if > 0 */,
p_out_bandwidth /* limit outgoing bandwith if > 0 */);
} else {
host = enet_host_create(NULL /* create a client host */,
1 /* only allow 1 outgoing connection */,
- SYSCH_MAX /* allow up to SYSCH_MAX channels to be used */,
+ channel_count /* allow up to channel_count to be used */,
p_in_bandwidth /* limit incoming bandwith if > 0 */,
p_out_bandwidth /* limit outgoing bandwith if > 0 */);
}
@@ -167,7 +183,7 @@ Error NetworkedMultiplayerENet::create_client(const String &p_address, int p_por
unique_id = _gen_unique_id();
// Initiate connection, allocating enough channels
- ENetPeer *peer = enet_host_connect(host, &address, SYSCH_MAX, unique_id);
+ ENetPeer *peer = enet_host_connect(host, &address, channel_count, unique_id);
if (peer == NULL) {
enet_host_destroy(host);
@@ -316,7 +332,7 @@ void NetworkedMultiplayerENet::poll() {
}
enet_packet_destroy(event.packet);
- } else if (event.channelID < SYSCH_MAX) {
+ } else if (event.channelID < channel_count) {
Packet packet;
packet.packet = event.packet;
@@ -330,6 +346,7 @@ void NetworkedMultiplayerENet::poll() {
uint32_t flags = decode_uint32(&event.packet->data[8]);
packet.from = source;
+ packet.channel = event.channelID;
if (server) {
// Someone is cheating and trying to fake the source!
@@ -496,7 +513,10 @@ Error NetworkedMultiplayerENet::put_packet(const uint8_t *p_buffer, int p_buffer
switch (transfer_mode) {
case TRANSFER_MODE_UNRELIABLE: {
- packet_flags = ENET_PACKET_FLAG_UNSEQUENCED;
+ if (always_ordered)
+ packet_flags = 0;
+ else
+ packet_flags = ENET_PACKET_FLAG_UNSEQUENCED;
channel = SYSCH_UNRELIABLE;
} break;
case TRANSFER_MODE_UNRELIABLE_ORDERED: {
@@ -509,6 +529,9 @@ Error NetworkedMultiplayerENet::put_packet(const uint8_t *p_buffer, int p_buffer
} break;
}
+ if (transfer_channel > SYSCH_CONFIG)
+ channel = transfer_channel;
+
Map<int, ENetPeer *>::Element *E = NULL;
if (target_peer != 0) {
@@ -572,6 +595,7 @@ void NetworkedMultiplayerENet::_pop_current_packet() {
enet_packet_destroy(current_packet.packet);
current_packet.packet = NULL;
current_packet.from = 0;
+ current_packet.channel = -1;
}
}
@@ -759,6 +783,40 @@ int NetworkedMultiplayerENet::get_peer_port(int p_peer_id) const {
#endif
}
+void NetworkedMultiplayerENet::set_transfer_channel(int p_channel) {
+
+ ERR_FAIL_COND(p_channel < -1 || p_channel >= channel_count);
+
+ if (p_channel == SYSCH_CONFIG) {
+ ERR_EXPLAIN("Channel " + itos(SYSCH_CONFIG) + " is reserved");
+ ERR_FAIL();
+ }
+ transfer_channel = p_channel;
+}
+
+int NetworkedMultiplayerENet::get_transfer_channel() const {
+ return transfer_channel;
+}
+
+void NetworkedMultiplayerENet::set_channel_count(int p_channel) {
+
+ ERR_FAIL_COND(active);
+ ERR_FAIL_COND(p_channel < SYSCH_MAX);
+ channel_count = p_channel;
+}
+
+int NetworkedMultiplayerENet::get_channel_count() const {
+ return channel_count;
+}
+
+void NetworkedMultiplayerENet::set_always_ordered(bool p_ordered) {
+ always_ordered = p_ordered;
+}
+
+bool NetworkedMultiplayerENet::is_always_ordered() const {
+ return always_ordered;
+}
+
void NetworkedMultiplayerENet::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_server", "port", "max_clients", "in_bandwidth", "out_bandwidth"), &NetworkedMultiplayerENet::create_server, DEFVAL(32), DEFVAL(0), DEFVAL(0));
@@ -771,7 +829,19 @@ void NetworkedMultiplayerENet::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_peer_address", "id"), &NetworkedMultiplayerENet::get_peer_address);
ClassDB::bind_method(D_METHOD("get_peer_port", "id"), &NetworkedMultiplayerENet::get_peer_port);
+ ClassDB::bind_method(D_METHOD("get_packet_channel"), &NetworkedMultiplayerENet::get_packet_channel);
+ ClassDB::bind_method(D_METHOD("get_last_packet_channel"), &NetworkedMultiplayerENet::get_last_packet_channel);
+ ClassDB::bind_method(D_METHOD("set_transfer_channel", "channel"), &NetworkedMultiplayerENet::set_transfer_channel);
+ ClassDB::bind_method(D_METHOD("get_transfer_channel"), &NetworkedMultiplayerENet::get_transfer_channel);
+ ClassDB::bind_method(D_METHOD("set_channel_count", "channels"), &NetworkedMultiplayerENet::set_channel_count);
+ ClassDB::bind_method(D_METHOD("get_channel_count"), &NetworkedMultiplayerENet::get_channel_count);
+ ClassDB::bind_method(D_METHOD("set_always_ordered", "ordered"), &NetworkedMultiplayerENet::set_always_ordered);
+ ClassDB::bind_method(D_METHOD("is_always_ordered"), &NetworkedMultiplayerENet::is_always_ordered);
+
ADD_PROPERTY(PropertyInfo(Variant::INT, "compression_mode", PROPERTY_HINT_ENUM, "None,Range Coder,FastLZ,ZLib,ZStd"), "set_compression_mode", "get_compression_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "transfer_channel"), "set_transfer_channel", "get_transfer_channel");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "channel_count"), "set_channel_count", "get_channel_count");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "always_ordered"), "set_always_ordered", "is_always_ordered");
BIND_ENUM_CONSTANT(COMPRESS_NONE);
BIND_ENUM_CONSTANT(COMPRESS_RANGE_CODER);
@@ -789,6 +859,9 @@ NetworkedMultiplayerENet::NetworkedMultiplayerENet() {
target_peer = 0;
current_packet.packet = NULL;
transfer_mode = TRANSFER_MODE_RELIABLE;
+ channel_count = SYSCH_MAX;
+ transfer_channel = -1;
+ always_ordered = false;
connection_status = CONNECTION_DISCONNECTED;
compression_mode = COMPRESS_NONE;
enet_compressor.context = this;
diff --git a/modules/enet/networked_multiplayer_enet.h b/modules/enet/networked_multiplayer_enet.h
index d481f5d496..705807d429 100644
--- a/modules/enet/networked_multiplayer_enet.h
+++ b/modules/enet/networked_multiplayer_enet.h
@@ -68,6 +68,9 @@ private:
int target_peer;
TransferMode transfer_mode;
+ int transfer_channel;
+ int channel_count;
+ bool always_ordered;
ENetEvent event;
ENetPeer *peer;
@@ -83,6 +86,7 @@ private:
ENetPacket *packet;
int from;
+ int channel;
};
CompressionMode compression_mode;
@@ -145,6 +149,15 @@ public:
void set_compression_mode(CompressionMode p_mode);
CompressionMode get_compression_mode() const;
+ int get_packet_channel() const;
+ int get_last_packet_channel() const;
+ void set_transfer_channel(int p_channel);
+ int get_transfer_channel() const;
+ void set_channel_count(int p_channel);
+ int get_channel_count() const;
+ void set_always_ordered(bool p_ordered);
+ bool is_always_ordered() const;
+
NetworkedMultiplayerENet();
~NetworkedMultiplayerENet();
diff --git a/modules/freetype/SCsub b/modules/freetype/SCsub
index 8a7c2a773a..301f218361 100644
--- a/modules/freetype/SCsub
+++ b/modules/freetype/SCsub
@@ -17,18 +17,15 @@ if env['builtin_freetype']:
"src/base/ftbitmap.c",
"src/base/ftcid.c",
"src/base/ftdebug.c",
- "src/base/ftfntfmt.c",
"src/base/ftfstype.c",
"src/base/ftgasp.c",
"src/base/ftglyph.c",
"src/base/ftgxval.c",
"src/base/ftinit.c",
- "src/base/ftlcdfil.c",
"src/base/ftmm.c",
"src/base/ftotval.c",
"src/base/ftpatent.c",
"src/base/ftpfr.c",
- "src/base/ftpic.c",
"src/base/ftstroke.c",
"src/base/ftsynth.c",
"src/base/ftsystem.c",
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 98ac7eec85..04632e8a11 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -850,16 +850,16 @@ struct _KeyCodeMap {
static const _KeyCodeMap _keycodes[55] = {
{ '`', KEY_QUOTELEFT },
{ '~', KEY_ASCIITILDE },
- { '0', KEY_KP_0 },
- { '1', KEY_KP_1 },
- { '2', KEY_KP_2 },
- { '3', KEY_KP_3 },
- { '4', KEY_KP_4 },
- { '5', KEY_KP_5 },
- { '6', KEY_KP_6 },
- { '7', KEY_KP_7 },
- { '8', KEY_KP_8 },
- { '9', KEY_KP_9 },
+ { '0', KEY_0 },
+ { '1', KEY_1 },
+ { '2', KEY_2 },
+ { '3', KEY_3 },
+ { '4', KEY_4 },
+ { '5', KEY_5 },
+ { '6', KEY_6 },
+ { '7', KEY_7 },
+ { '8', KEY_8 },
+ { '9', KEY_9 },
{ '-', KEY_MINUS },
{ '_', KEY_UNDERSCORE },
{ '=', KEY_EQUAL },
diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp
index 5512fd4f10..0577a23ea6 100644
--- a/scene/3d/physics_body.cpp
+++ b/scene/3d/physics_body.cpp
@@ -1825,6 +1825,7 @@ void PhysicalBone::_notification(int p_what) {
parent_skeleton = find_skeleton_parent(get_parent());
update_bone_id();
reset_to_rest_position();
+ _reset_physics_simulation_state();
break;
case NOTIFICATION_EXIT_TREE:
if (parent_skeleton) {
@@ -1886,10 +1887,8 @@ void PhysicalBone::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_body_offset", "offset"), &PhysicalBone::set_body_offset);
ClassDB::bind_method(D_METHOD("get_body_offset"), &PhysicalBone::get_body_offset);
- ClassDB::bind_method(D_METHOD("set_static_body", "simulate"), &PhysicalBone::set_static_body);
ClassDB::bind_method(D_METHOD("is_static_body"), &PhysicalBone::is_static_body);
- ClassDB::bind_method(D_METHOD("set_simulate_physics", "simulate"), &PhysicalBone::set_simulate_physics);
ClassDB::bind_method(D_METHOD("get_simulate_physics"), &PhysicalBone::get_simulate_physics);
ClassDB::bind_method(D_METHOD("is_simulating_physics"), &PhysicalBone::is_simulating_physics);
@@ -1913,9 +1912,7 @@ void PhysicalBone::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "joint_type", PROPERTY_HINT_ENUM, "None,PinJoint,ConeJoint,HingeJoint,SliderJoint,6DOFJoint"), "set_joint_type", "get_joint_type");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "joint_offset"), "set_joint_offset", "get_joint_offset");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "simulate_physics"), "set_simulate_physics", "get_simulate_physics");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "body_offset"), "set_body_offset", "get_body_offset");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "static_body"), "set_static_body", "is_static_body");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "mass", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_mass", "get_mass");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "weight", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_weight", "get_weight");
@@ -2255,8 +2252,8 @@ PhysicalBone::PhysicalBone() :
joint_data(NULL),
static_body(false),
simulate_physics(false),
- _internal_static_body(!static_body),
- _internal_simulate_physics(simulate_physics),
+ _internal_static_body(false),
+ _internal_simulate_physics(false),
bone_id(-1),
parent_skeleton(NULL),
bone_name(""),
diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp
index a7eb54c85d..76d90dc6ff 100644
--- a/scene/3d/skeleton.cpp
+++ b/scene/3d/skeleton.cpp
@@ -330,7 +330,7 @@ void Skeleton::add_bone(const String &p_name) {
_make_dirty();
update_gizmo();
}
-int Skeleton::find_bone(String p_name) const {
+int Skeleton::find_bone(const String &p_name) const {
for (int i = 0; i < bones.size(); i++) {
@@ -347,6 +347,19 @@ String Skeleton::get_bone_name(int p_bone) const {
return bones[p_bone].name;
}
+bool Skeleton::is_bone_parent_of(int p_bone, int p_parent_bone_id) const {
+
+ int parent_of_bone = get_bone_parent(p_bone);
+
+ if (-1 == parent_of_bone)
+ return false;
+
+ if (parent_of_bone == p_parent_bone_id)
+ return true;
+
+ return is_bone_parent_of(parent_of_bone, p_parent_bone_id);
+}
+
int Skeleton::get_bone_count() const {
return bones.size();
@@ -534,18 +547,6 @@ void Skeleton::localize_rests() {
}
}
-void _notify_physical_bones_simulation(bool start, Node *p_node) {
-
- for (int i = p_node->get_child_count() - 1; 0 <= i; --i) {
- _notify_physical_bones_simulation(start, p_node->get_child(i));
- }
-
- PhysicalBone *pb = Object::cast_to<PhysicalBone>(p_node);
- if (pb) {
- pb->set_simulate_physics(start);
- }
-}
-
void Skeleton::bind_physical_bone_to_bone(int p_bone, PhysicalBone *p_physical_bone) {
ERR_FAIL_INDEX(p_bone, bones.size());
ERR_FAIL_COND(bones[p_bone].physical_bone);
@@ -603,8 +604,67 @@ void Skeleton::_rebuild_physical_bones_cache() {
}
}
-void Skeleton::physical_bones_simulation(bool start) {
- _notify_physical_bones_simulation(start, this);
+void _pb_stop_simulation(Node *p_node) {
+
+ for (int i = p_node->get_child_count() - 1; 0 <= i; --i) {
+ _pb_stop_simulation(p_node->get_child(i));
+ }
+
+ PhysicalBone *pb = Object::cast_to<PhysicalBone>(p_node);
+ if (pb) {
+ pb->set_simulate_physics(false);
+ pb->set_static_body(false);
+ }
+}
+
+void Skeleton::physical_bones_stop_simulation() {
+ _pb_stop_simulation(this);
+}
+
+void _pb_start_simulation(const Skeleton *p_skeleton, Node *p_node, const Vector<int> &p_sim_bones) {
+
+ for (int i = p_node->get_child_count() - 1; 0 <= i; --i) {
+ _pb_start_simulation(p_skeleton, p_node->get_child(i), p_sim_bones);
+ }
+
+ PhysicalBone *pb = Object::cast_to<PhysicalBone>(p_node);
+ if (pb) {
+ bool sim = false;
+ for (int i = p_sim_bones.size() - 1; 0 <= i; --i) {
+ if (p_sim_bones[i] == pb->get_bone_id() || p_skeleton->is_bone_parent_of(pb->get_bone_id(), p_sim_bones[i])) {
+ sim = true;
+ break;
+ }
+ }
+
+ pb->set_simulate_physics(true);
+ if (sim) {
+ pb->set_static_body(false);
+ } else {
+ pb->set_static_body(true);
+ }
+ }
+}
+
+void Skeleton::physical_bones_start_simulation_on(const Array &p_bones) {
+
+ Vector<int> sim_bones;
+ if (p_bones.size() <= 0) {
+ sim_bones.push_back(0); // if no bones is specified, activate ragdoll on full body
+ } else {
+ sim_bones.resize(p_bones.size());
+ int c = 0;
+ for (int i = sim_bones.size() - 1; 0 <= i; --i) {
+ if (Variant::STRING == p_bones.get(i).get_type()) {
+ int bone_id = find_bone(p_bones.get(i));
+ if (bone_id != -1)
+ sim_bones[c++] = bone_id;
+ }
+ }
+ sim_bones.resize(c);
+ }
+
+ _pb_start_simulation(this, this, sim_bones);
}
void _physical_bones_add_remove_collision_exception(bool p_add, Node *p_node, RID p_exception) {
@@ -667,7 +727,8 @@ void Skeleton::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_bone_transform", "bone_idx"), &Skeleton::get_bone_transform);
- ClassDB::bind_method(D_METHOD("physical_bones_simulation", "start"), &Skeleton::physical_bones_simulation);
+ ClassDB::bind_method(D_METHOD("physical_bones_stop_simulation"), &Skeleton::physical_bones_stop_simulation);
+ ClassDB::bind_method(D_METHOD("physical_bones_start_simulation", "bones"), &Skeleton::physical_bones_start_simulation_on, DEFVAL(Array()));
ClassDB::bind_method(D_METHOD("physical_bones_add_collision_exception", "exception"), &Skeleton::physical_bones_add_collision_exception);
ClassDB::bind_method(D_METHOD("physical_bones_remove_collision_exception", "exception"), &Skeleton::physical_bones_remove_collision_exception);
@@ -683,6 +744,5 @@ Skeleton::Skeleton() {
}
Skeleton::~Skeleton() {
-
VisualServer::get_singleton()->free(skeleton);
}
diff --git a/scene/3d/skeleton.h b/scene/3d/skeleton.h
index f0e71c8b4f..dad11960a5 100644
--- a/scene/3d/skeleton.h
+++ b/scene/3d/skeleton.h
@@ -120,9 +120,11 @@ public:
// skeleton creation api
void add_bone(const String &p_name);
- int find_bone(String p_name) const;
+ int find_bone(const String &p_name) const;
String get_bone_name(int p_bone) const;
+ bool is_bone_parent_of(int p_bone_id, int p_parent_bone_id) const;
+
void set_bone_parent(int p_bone, int p_parent);
int get_bone_parent(int p_bone) const;
@@ -176,7 +178,8 @@ private:
void _rebuild_physical_bones_cache();
public:
- void physical_bones_simulation(bool start);
+ void physical_bones_stop_simulation();
+ void physical_bones_start_simulation_on(const Array &p_bones);
void physical_bones_add_collision_exception(RID p_exception);
void physical_bones_remove_collision_exception(RID p_exception);