May 17, 2015
Using HTTPClient in Godot
Hi all,
While I was creating an openclipart plugin for the Godot Engine, I have created an HTTP class for downloading the data and images. Godot has built-in support for HTTP get/post data. An example on how to use the HTTPClient is already available on godot github wiki page.
The plugin loads multiple images simultaneously so I was in need of creating a class for that. Also there are multiple things are loaded, there is a chance of blocking the UI. Here comes multi-threading to the rescue. Godot wiki also has an example for background resource loading in another thread.
I combined these two and now the HTTP class uses a thread to load data. I also added two signals – loading and loaded. The HTTP header ‘Content-length’ is checked using http.get_response_body_length(). So the signal ‘loading’ emits with two values – bytes loaded and bytes total. From those we can find the percent loaded. The signal ‘loaded’ emits with the result value.
Create a new Node in godot and add this script and save it as a scene ‘http.xml’.
extends Node var t = Thread.new() func _init(): var arg_bytes_loaded = {"name":"bytes_loaded","type":TYPE_INT} var arg_bytes_total = {"name":"bytes_total","type":TYPE_INT} add_user_signal("loading",[arg_bytes_loaded,arg_bytes_total]) var arg_result = {"name":"result","type":TYPE_RAW_ARRAY} add_user_signal("loaded",[arg_result]) pass func get(domain,url,port,ssl): if(t.is_active()): return t.start(self,"_load",{"domain":domain,"url":url,"port":port,"ssl":ssl}) func _load(params): var err = 0 var http = HTTPClient.new() err = http.connect(params.domain,params.port,params.ssl) while(http.get_status() == HTTPClient.STATUS_CONNECTING or http.get_status() == HTTPClient.STATUS_RESOLVING): http.poll() OS.delay_msec(100) var headers = [ "User-Agent: Pirulo/1.0 (Godot)", "Accept: */*" ] err = http.request(HTTPClient.METHOD_GET,params.url,headers) while (http.get_status() == HTTPClient.STATUS_REQUESTING): http.poll() OS.delay_msec(500) # var rb = RawArray() if(http.has_response()): var headers = http.get_response_headers_as_dictionary() while(http.get_status()==HTTPClient.STATUS_BODY): http.poll() var chunk = http.read_response_body_chunk() if(chunk.size()==0): OS.delay_usec(100) else: rb = rb+chunk call_deferred("_send_loading_signal",rb.size(),http.get_response_body_length()) call_deferred("_send_loaded_signal") http.close() return rb func _send_loading_signal(l,t): emit_signal("loading",l,t) pass func _send_loaded_signal(): var r = t.wait_to_finish() emit_signal("loaded",r) pass
Sample usage:
var http = preload('http.xml').instance() http.connect("loading",self,"_on_loading") http.connect("loaded",self,"_on_loaded") http.get("http://example.com","/page?id=1",80,false) #domain,url,port,useSSL func _on_loading(loaded,total): var percent = loaded*100/total func _on_loaded(result): var result_string = result.get_string_from_ascii() print(result_string)
The class now supports only get method. We will look into the ‘post’ method later.
Thanks.
[Total: 13 Average: 2.8/5]