Docs: Port Code Examples to C# (F, G, H, I, J, K, L)

Includes:
 * File
 * Geometry2D
 * HashingContext
 * HTTPClient
 * HTTPRequest
 * Image
 * Input
 * int
 * ItemList
 * JSONParseResult
 * KinematicBody2D
 * LineEdit

Co-authored-by: Aaron Franke <arnfranke@yahoo.com>
This commit is contained in:
HaSa1002 2020-10-31 00:37:55 +01:00
parent 91f7df2b4c
commit 5a01c2a3b0
11 changed files with 289 additions and 43 deletions

View File

@ -6,7 +6,8 @@
<description>
File type. This is used to permanently store data into the user device's file system and to read from it. This can be used to store game save data or player configuration files, for example.
Here's a sample on how to write and read from a file:
[codeblock]
[codeblocks]
[gdscript]
func save(content):
var file = File.new()
file.open("user://save_game.dat", File.WRITE)
@ -19,7 +20,26 @@
var content = file.get_as_text()
file.close()
return content
[/codeblock]
[/gdscript]
[csharp]
public void Save(string content)
{
var file = new File();
file.Open("user://save_game.dat", File.ModeFlags.Write);
file.StoreString(content);
file.Close();
}
public string Load()
{
var file = new File();
file.Open("user://save_game.dat", File.ModeFlags.Read);
string content = file.GetAsText();
file.Close();
return content;
}
[/csharp]
[/codeblocks]
In the example above, the file will be saved in the user data folder as specified in the [url=https://docs.godotengine.org/en/latest/tutorials/io/data_paths.html]Data paths[/url] documentation.
[b]Note:[/b] To access project resources once exported, it is recommended to use [ResourceLoader] instead of the [File] API, as some files are converted to engine-specific formats and their original source files might not be present in the exported PCK package.
</description>
@ -303,7 +323,8 @@
Stores an integer as 16 bits in the file.
[b]Note:[/b] The [code]value[/code] should lie in the interval [code][0, 2^16 - 1][/code]. Any other value will overflow and wrap around.
To store a signed integer, use [method store_64] or store a signed integer from the interval [code][-2^15, 2^15 - 1][/code] (i.e. keeping one bit for the signedness) and compute its sign manually when reading. For example:
[codeblock]
[codeblocks]
[gdscript]
const MAX_15B = 1 &lt;&lt; 15
const MAX_16B = 1 &lt;&lt; 16
@ -320,7 +341,22 @@
var read2 = f.get_16() # 121
var converted1 = unsigned16_to_signed(read1) # -42
var converted2 = unsigned16_to_signed(read2) # 121
[/codeblock]
[/gdscript]
[csharp]
public override void _Ready()
{
var f = new File();
f.Open("user://file.dat", File.ModeFlags.WriteRead);
f.Store16(unchecked((ushort)-42)); // This wraps around and stores 65494 (2^16 - 42).
f.Store16(121); // In bounds, will store 121.
f.Seek(0); // Go back to start to read the stored value.
ushort read1 = f.Get16(); // 65494
ushort read2 = f.Get16(); // 121
short converted1 = BitConverter.ToInt16(BitConverter.GetBytes(read1), 0); // -42
short converted2 = BitConverter.ToInt16(BitConverter.GetBytes(read2), 0); // 121
}
[/csharp]
[/codeblocks]
</description>
</method>
<method name="store_32">

View File

@ -201,12 +201,21 @@
Each polygon's vertices will be rounded as determined by [code]join_type[/code], see [enum PolyJoinType].
The operation may result in an outer polygon (boundary) and inner polygon (hole) produced which could be distinguished by calling [method is_polygon_clockwise].
[b]Note:[/b] To translate the polygon's vertices specifically, multiply them to a [Transform2D]:
[codeblock]
[codeblocks]
[gdscript]
var polygon = PackedVector2Array([Vector2(0, 0), Vector2(100, 0), Vector2(100, 100), Vector2(0, 100)])
var offset = Vector2(50, 50)
polygon = Transform2D(0, offset) * polygon
print(polygon) # prints [Vector2(50, 50), Vector2(150, 50), Vector2(150, 150), Vector2(50, 150)]
[/codeblock]
[/gdscript]
[csharp]
var polygon = new Vector2[] { new Vector2(0, 0), new Vector2(100, 0), new Vector2(100, 100), new Vector2(0, 100) };
var offset = new Vector2(50, 50);
// TODO: This code is not valid right now. Ping @aaronfranke about it before Godot 4.0 is out.
//polygon = (Vector2[]) new Transform2D(0, offset).Xform(polygon);
//GD.Print(polygon); // prints [Vector2(50, 50), Vector2(150, 50), Vector2(150, 150), Vector2(50, 150)]
[/csharp]
[/codeblocks]
</description>
</method>
<method name="offset_polyline">

View File

@ -112,17 +112,31 @@
</argument>
<description>
Generates a GET/POST application/x-www-form-urlencoded style query string from a provided dictionary, e.g.:
[codeblock]
[codeblocks]
[gdscript]
var fields = {"username": "user", "password": "pass"}
var query_string = http_client.query_string_from_dict(fields)
# Returns "username=user&amp;password=pass"
[/codeblock]
[/gdscript]
[csharp]
var fields = new Godot.Collections.Dictionary { { "username", "user" }, { "password", "pass" } };
string queryString = new HTTPClient().QueryStringFromDict(fields);
// Returns "username=user&amp;password=pass"
[/csharp]
[/codeblocks]
Furthermore, if a key has a [code]null[/code] value, only the key itself is added, without equal sign and value. If the value is an array, for each value in it a pair with the same key is added.
[codeblock]
[codeblocks]
[gdscript]
var fields = {"single": 123, "not_valued": null, "multiple": [22, 33, 44]}
var query_string = http_client.query_string_from_dict(fields)
# Returns "single=123&amp;not_valued&amp;multiple=22&amp;multiple=33&amp;multiple=44"
[/codeblock]
[/gdscript]
[csharp]
var fields = new Godot.Collections.Dictionary{{"single", 123}, {"notValued", null}, {"multiple", new Godot.Collections.Array{22, 33, 44}}};
string queryString = new HTTPClient().QueryStringFromDict(fields);
// Returns "single=123&amp;not_valued&amp;multiple=22&amp;multiple=33&amp;multiple=44"
[/csharp]
[/codeblocks]
</description>
</method>
<method name="read_response_body_chunk">
@ -147,12 +161,20 @@
Sends a request to the connected host. The URL parameter is just the part after the host, so for [code]http://somehost.com/index.php[/code], it is [code]index.php[/code].
Headers are HTTP request headers. For available HTTP methods, see [enum Method].
To create a POST request with query strings to push to the server, do:
[codeblock]
[codeblocks]
[gdscript]
var fields = {"username" : "user", "password" : "pass"}
var query_string = http_client.query_string_from_dict(fields)
var headers = ["Content-Type: application/x-www-form-urlencoded", "Content-Length: " + str(query_string.length())]
var result = http_client.request(http_client.METHOD_POST, "index.php", headers, query_string)
[/codeblock]
[/gdscript]
[csharp]
var fields = new Godot.Collections.Dictionary { { "username", "user" }, { "password", "pass" } };
string queryString = new HTTPClient().QueryStringFromDict(fields);
string[] headers = {"Content-Type: application/x-www-form-urlencoded", "Content-Length: " + queryString.Length};
var result = new HTTPClient().Request(HTTPClient.Method.Post, "index.php", headers, queryString);
[/csharp]
[/codeblocks]
[b]Note:[/b] The [code]request_data[/code] parameter is ignored if [code]method[/code] is [constant HTTPClient.METHOD_GET]. This is because GET methods can't contain request data. As a workaround, you can pass request data as a query string in the URL. See [method String.http_escape] for an example.
</description>
</method>

View File

@ -7,7 +7,8 @@
A node with the ability to send HTTP requests. Uses [HTTPClient] internally.
Can be used to make HTTP requests, i.e. download or upload files or web content via HTTP.
[b]Example of contacting a REST API and printing one of its returned fields:[/b]
[codeblock]
[codeblocks]
[gdscript]
func _ready():
# Create an HTTP request node and connect its completion signal.
var http_request = HTTPRequest.new()
@ -34,9 +35,48 @@
# Will print the user agent string used by the HTTPRequest node (as recognized by httpbin.org).
print(response.headers["User-Agent"])
[/codeblock]
[/gdscript]
[csharp]
public override void _Ready()
{
// Create an HTTP request node and connect its completion signal.
var httpRequest = new HTTPRequest();
AddChild(httpRequest);
httpRequest.Connect("request_completed", this, nameof(HttpRequestCompleted));
// Perform a GET request. The URL below returns JSON as of writing.
Error error = httpRequest.Request("https://httpbin.org/get");
if (error != Error.Ok)
{
GD.PushError("An error occurred in the HTTP request.");
}
// Perform a POST request. The URL below returns JSON as of writing.
// Note: Don't make simultaneous requests using a single HTTPRequest node.
// The snippet below is provided for reference only.
string[] body = { "name", "Godette" };
// GDScript to_json is non existent, so we use JSON.Print() here.
error = httpRequest.Request("https://httpbin.org/post", null, true, HTTPClient.Method.Post, JSON.Print(body));
if (error != Error.Ok)
{
GD.PushError("An error occurred in the HTTP request.");
}
}
// Called when the HTTP request is completed.
private void HttpRequestCompleted(int result, int response_code, string[] headers, byte[] body)
{
// GDScript parse_json is non existent so we have to use JSON.parse, which has a slightly different syntax.
var response = JSON.Parse(body.GetStringFromUTF8()).Result as Godot.Collections.Dictionary;
// Will print the user agent string used by the HTTPRequest node (as recognized by httpbin.org).
GD.Print((response["headers"] as Godot.Collections.Dictionary)["User-Agent"]);
}
[/csharp]
[/codeblocks]
[b]Example of loading and displaying an image using HTTPRequest:[/b]
[codeblock]
[codeblocks]
[gdscript]
func _ready():
# Create an HTTP request node and connect its completion signal.
var http_request = HTTPRequest.new()
@ -51,6 +91,9 @@
# Called when the HTTP request is completed.
func _http_request_completed(result, response_code, headers, body):
if result != HTTPRequest.RESULT_SUCCESS:
push_error("Image couldn't be downloaded. Try a different image.")
var image = Image.new()
var error = image.load_png_from_buffer(body)
if error != OK:
@ -63,7 +106,48 @@
var texture_rect = TextureRect.new()
add_child(texture_rect)
texture_rect.texture = texture
[/codeblock]
[/gdscript]
[csharp]
public override void _Ready()
{
// Create an HTTP request node and connect its completion signal.
var httpRequest = new HTTPRequest();
AddChild(httpRequest);
httpRequest.Connect("request_completed", this, nameof(HttpRequestCompleted));
// Perform the HTTP request. The URL below returns a PNG image as of writing.
Error error = httpRequest.Request("https://via.placeholder.com/512");
if (error != Error.Ok)
{
GD.PushError("An error occurred in the HTTP request.");
}
}
// Called when the HTTP request is completed.
private void HttpRequestCompleted(int result, int response_code, string[] headers, byte[] body)
{
if (result != (int)HTTPRequest.Result.Success)
{
GD.PushError("Image couldn't be downloaded. Try a different image.");
}
var image = new Image();
Error error = image.LoadPngFromBuffer(body);
if (error != Error.Ok)
{
GD.PushError("Couldn't load the image.");
}
var texture = new ImageTexture();
texture.CreateFromImage(image);
// Display the image in a TextureRect node.
var textureRect = new TextureRect();
AddChild(textureRect);
textureRect.Texture = texture;
}
[/csharp]
[/codeblocks]
[b]Gzipped response bodies[/b]: HTTPRequest will automatically handle decompression of response bodies. A [code]Accept-Encoding[/code] header will be automatically added to each of your requests, unless one is already specified. Any response with a [code]Content-Encoding: gzip[/code] header will automatically be decompressed and delivered to you as uncompressed bytes.
[b]Note:[/b] When performing HTTP requests from a project exported to HTML5, keep in mind the remote server may not allow requests from foreign origins due to [url=https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS]CORS[/url]. If you host the server in question, you should modify its backend to allow requests from foreign origins by adding the [code]Access-Control-Allow-Origin: *[/code] HTTP header.

View File

@ -6,8 +6,9 @@
<description>
The HashingContext class provides an interface for computing cryptographic hashes over multiple iterations. This is useful for example when computing hashes of big files (so you don't have to load them all in memory), network streams, and data streams in general (so you don't have to hold buffers).
The [enum HashType] enum shows the supported hashing algorithms.
[codeblock]
const CHUNK_SIZE = 1024
[codeblocks]
[gdscript]
const CHUNK_SIZE = 102
func hash_file(path):
var ctx = HashingContext.new()
@ -26,7 +27,36 @@
var res = ctx.finish()
# Print the result as hex string and array.
printt(res.hex_encode(), Array(res))
[/codeblock]
[/gdscript]
[csharp]
public const int ChunkSize = 1024;
public void HashFile(string path)
{
var ctx = new HashingContext();
var file = new File();
// Start a SHA-256 context.
ctx.Start(HashingContext.HashType.Sha256);
// Check that file exists.
if (!file.FileExists(path))
{
return;
}
// Open the file to hash.
file.Open(path, File.ModeFlags.Read);
// Update the context after reading each chunk.
while (!file.EofReached())
{
ctx.Update(file.GetBuffer(ChunkSize));
}
// Get the computed hash.
byte[] res = ctx.Finish();
// Print the result as hex string and array.
GD.PrintT(res.HexEncode(), res);
}
[/csharp]
[/codeblocks]
[b]Note:[/b] Not available in HTML5 exports.
</description>
<tutorials>

View File

@ -299,12 +299,20 @@
<description>
Feeds an [InputEvent] to the game. Can be used to artificially trigger input events from code. Also generates [method Node._input] calls.
Example:
[codeblock]
var a = InputEventAction.new()
a.action = "ui_cancel"
a.pressed = true
Input.parse_input_event(a)
[/codeblock]
[codeblocks]
[gdscript]
var cancel_event = InputEventAction.new()
cancel_event.action = "ui_cancel"
cancel_event.pressed = true
Input.parse_input_event(cancel_event)
[/gdscript]
[csharp]
var cancelEvent = new InputEventAction();
cancelEvent.Action = "ui_cancel";
cancelEvent.Pressed = true;
Input.ParseInputEvent(cancelEvent);
[/csharp]
[/codeblocks]
</description>
</method>
<method name="remove_joy_mapping">

View File

@ -247,11 +247,16 @@
<argument index="1" name="custom_bg_color" type="Color">
</argument>
<description>
Sets the background color of the item specified by [code]idx[/code] index to the specified [Color].
[codeblock]
var some_string = "Some text"
some_string.set_item_custom_bg_color(0,Color(1, 0, 0, 1) # This will set the background color of the first item of the control to red.
[/codeblock]
[codeblocks]
[gdscript]
var itemList = ItemList.new()
some_string.set_item_custom_bg_color(0, Color.red) # This will set the background color of the first item of the control to red.
[/gdscript]
[csharp]
var itemList = new ItemList();
itemList.SetItemCustomBgColor(0, Colors.Red); // This will set the background color of the first item of the control to red.
[/csharp]
[/codeblocks]
</description>
</method>
<method name="set_item_custom_fg_color">
@ -263,10 +268,16 @@
</argument>
<description>
Sets the foreground color of the item specified by [code]idx[/code] index to the specified [Color].
[codeblock]
var some_string = "Some text"
some_string.set_item_custom_fg_color(0,Color(1, 0, 0, 1) # This will set the foreground color of the first item of the control to red.
[/codeblock]
[codeblocks]
[gdscript]
var item_list = ItemList.new()
item_list.set_item_custom_fg_color(0, Color.red) # This will set the foreground color of the first item of the control to red.
[/gdscript]
[csharp]
var itemList = new ItemList();
itemList.SetItemCustomFgColor(0, Colors.Red); // This will set the foreground color of the first item of the control to red.
[/csharp]
[/codeblocks]
</description>
</method>
<method name="set_item_disabled">

View File

@ -24,13 +24,26 @@
A [Variant] containing the parsed JSON. Use [method @GDScript.typeof] or the [code]is[/code] keyword to check if it is what you expect. For example, if the JSON source starts with curly braces ([code]{}[/code]), a [Dictionary] will be returned. If the JSON source starts with brackets ([code][][/code]), an [Array] will be returned.
[b]Note:[/b] The JSON specification does not define integer or float types, but only a [i]number[/i] type. Therefore, parsing a JSON text will convert all numerical values to [float] types.
[b]Note:[/b] JSON objects do not preserve key order like Godot dictionaries, thus, you should not rely on keys being in a certain order if a dictionary is constructed from JSON. In contrast, JSON arrays retain the order of their elements:
[codeblock]
[codeblocks]
[gdscript]
var p = JSON.parse('["hello", "world", "!"]')
if typeof(p.result) == TYPE_ARRAY:
print(p.result[0]) # Prints "hello"
else:
push_error("Unexpected results.")
[/codeblock]
[/gdscript]
[csharp]
JSONParseResult p = JSON.Parse("[\"hello\"], \"world\", \"!\"]");
if (p.Result is Godot.Collections.Array)
{
GD.Print((p.Result as Godot.Collections.Array)[0]); // Prints "hello"
}
else
{
GD.PushError("Unexpected results.");
}
[/csharp]
[/codeblocks]
</member>
</members>
<constants>

View File

@ -37,11 +37,20 @@
<description>
Returns a [KinematicCollision2D], which contains information about a collision that occurred during the last call to [method move_and_slide] or [method move_and_slide_with_snap]. Since the body can collide several times in a single call to [method move_and_slide], you must specify the index of the collision in the range 0 to ([method get_slide_count] - 1).
[b]Example usage:[/b]
[codeblock]
[codeblocks]
[gdscript]
for i in get_slide_count():
var collision = get_slide_collision(i)
print("Collided with: ", collision.collider.name)
[/codeblock]
[/gdscript]
[csharp]
for (int i = 0; i &lt; GetSlideCount(); i++)
{
KinematicCollision2D collision = GetSlideCollision(i);
GD.Print("Collided with: ", (collision.Collider as Node).Name);
}
[/csharp]
[/codeblocks]
</description>
</method>
<method name="get_slide_count" qualifiers="const">

View File

@ -103,12 +103,20 @@
</argument>
<description>
Selects characters inside [LineEdit] between [code]from[/code] and [code]to[/code]. By default, [code]from[/code] is at the beginning and [code]to[/code] at the end.
[codeblock]
[codeblocks]
[gdscript]
text = "Welcome"
select() # Will select "Welcome".
select(4) # Will select "ome".
select(2, 5) # Will select "lco".
[/codeblock]
[/gdscript]
[csharp]
Text = "Welcome";
Select(); // Will select "Welcome".
Select(4); // Will select "ome".
Select(2, 5); // Will select "lco".
[/csharp]
[/codeblocks]
</description>
</method>
<method name="select_all">

View File

@ -7,18 +7,34 @@
Signed 64-bit integer type.
It can take values in the interval [code][-2^63, 2^63 - 1][/code], i.e. [code][-9223372036854775808, 9223372036854775807][/code]. Exceeding those bounds will wrap around.
[int] is a [Variant] type, and will thus be used when assigning an integer value to a [Variant]. It can also be enforced with the [code]: int[/code] type hint.
[codeblock]
[codeblocks]
[gdscript]
var my_variant = 0 # int, value 0.
my_variant += 4.2 # float, value 4.2.
var my_int: int = 1 # int, value 1.
my_int = 4.2 # int, value 4, the right value is implicitly cast to int.
my_int = int("6.7") # int, value 6, the String is explicitly cast with int.
var max_int = 9223372036854775807
print(max_int) # 9223372036854775807, OK.
max_int += 1
print(max_int) # -9223372036854775808, we overflowed and wrapped around.
[/codeblock]
[/gdscript]
[csharp]
int myInt = (int)"6.7".ToFloat(); // int, value 6, the String is explicitly cast with int.
// We have to use `long` here, because GDSript's `int`
// is 64 bits long while C#'s `int` is only 32 bits.
long maxInt = 9223372036854775807;
GD.Print(maxInt); // 9223372036854775807, OK.
maxInt++;
GD.Print(maxInt); // -9223372036854775808, we overflowed and wrapped around.
// Alternatively, if we used C#'s 32-bit `int` type, the maximum value is much smaller:
int halfInt = 2147483647;
GD.Print(halfInt); // 2147483647, OK.
halfInt++;
GD.Print(halfInt); // -2147483648, we overflowed and wrapped around.
[/csharp]
[/codeblocks]
</description>
<tutorials>
</tutorials>