-Made editor support SSL certs by default (embedded them)
-Made asset sharing support https -Many fixes to HTTPRequest -Added an asset installer dialog -Visual cleanups to asset sharing tab -Fixed some issues in ScrollContainer, hope it does not break things -Asset sharing tab is not visible (hidden on purpose) for now.
This commit is contained in:
parent
d85f06c42d
commit
8b1dcbfe4d
32 changed files with 6011 additions and 142 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -18,6 +18,7 @@ core/global_defaults.cpp
|
|||
drivers/unix/os_unix_global_settings_path.cpp
|
||||
tools/editor/register_exporters.cpp
|
||||
tools/editor/doc_data_compressed.h
|
||||
tools/editor/certs_compressed.h
|
||||
tools/editor/editor_icons.cpp
|
||||
-fpic
|
||||
.fscache
|
||||
|
|
|
@ -2214,6 +2214,8 @@ void Image::blit_rect(const Image& p_src, const Rect2& p_src_rect,const Point2&
|
|||
|
||||
|
||||
Image (*Image::_png_mem_loader_func)(const uint8_t*,int)=NULL;
|
||||
Image (*Image::_jpg_mem_loader_func)(const uint8_t*,int)=NULL;
|
||||
|
||||
void (*Image::_image_compress_bc_func)(Image *)=NULL;
|
||||
void (*Image::_image_compress_pvrtc2_func)(Image *)=NULL;
|
||||
void (*Image::_image_compress_pvrtc4_func)(Image *)=NULL;
|
||||
|
@ -2388,7 +2390,7 @@ String Image::get_format_name(Format p_format) {
|
|||
return format_names[p_format];
|
||||
}
|
||||
|
||||
Image::Image(const uint8_t* p_png,int p_len) {
|
||||
Image::Image(const uint8_t* p_mem_png_jpg, int p_len) {
|
||||
|
||||
width=0;
|
||||
height=0;
|
||||
|
@ -2396,8 +2398,13 @@ Image::Image(const uint8_t* p_png,int p_len) {
|
|||
format=FORMAT_GRAYSCALE;
|
||||
|
||||
if (_png_mem_loader_func) {
|
||||
*this = _png_mem_loader_func(p_png,p_len);
|
||||
*this = _png_mem_loader_func(p_mem_png_jpg,p_len);
|
||||
}
|
||||
|
||||
if (empty() && _jpg_mem_loader_func) {
|
||||
*this = _jpg_mem_loader_func(p_mem_png_jpg,p_len);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Image::Image() {
|
||||
|
|
|
@ -97,6 +97,7 @@ public:
|
|||
};
|
||||
|
||||
static Image (*_png_mem_loader_func)(const uint8_t* p_png,int p_size);
|
||||
static Image (*_jpg_mem_loader_func)(const uint8_t* p_png,int p_size);
|
||||
static void (*_image_compress_bc_func)(Image *);
|
||||
static void (*_image_compress_pvrtc2_func)(Image *);
|
||||
static void (*_image_compress_pvrtc4_func)(Image *);
|
||||
|
@ -355,7 +356,7 @@ public:
|
|||
static void set_compress_bc_func(void (*p_compress_func)(Image *));
|
||||
static String get_format_name(Format p_format);
|
||||
|
||||
Image(const uint8_t* p_mem_png, int p_len=-1);
|
||||
Image(const uint8_t* p_mem_png_jpg, int p_len=-1);
|
||||
Image(const char **p_xpm);
|
||||
~Image();
|
||||
|
||||
|
|
|
@ -4,12 +4,28 @@
|
|||
StreamPeerSSL* (*StreamPeerSSL::_create)()=NULL;
|
||||
|
||||
|
||||
|
||||
|
||||
StreamPeerSSL *StreamPeerSSL::create() {
|
||||
|
||||
return _create();
|
||||
}
|
||||
|
||||
|
||||
|
||||
StreamPeerSSL::LoadCertsFromMemory StreamPeerSSL::load_certs_func=NULL;
|
||||
bool StreamPeerSSL::available=false;
|
||||
bool StreamPeerSSL::initialize_certs=true;
|
||||
|
||||
void StreamPeerSSL::load_certs_from_memory(const ByteArray& p_memory) {
|
||||
if (load_certs_func)
|
||||
load_certs_func(p_memory);
|
||||
}
|
||||
|
||||
bool StreamPeerSSL::is_available() {
|
||||
return available;
|
||||
}
|
||||
|
||||
void StreamPeerSSL::_bind_methods() {
|
||||
|
||||
|
||||
|
|
|
@ -5,11 +5,23 @@
|
|||
|
||||
class StreamPeerSSL : public StreamPeer {
|
||||
OBJ_TYPE(StreamPeerSSL,StreamPeer);
|
||||
public:
|
||||
|
||||
typedef void (*LoadCertsFromMemory)(const ByteArray& p_certs);
|
||||
protected:
|
||||
static StreamPeerSSL* (*_create)();
|
||||
static void _bind_methods();
|
||||
|
||||
static LoadCertsFromMemory load_certs_func;
|
||||
static bool available;
|
||||
|
||||
|
||||
friend class Main;
|
||||
static bool initialize_certs;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
enum Status {
|
||||
STATUS_DISCONNECTED,
|
||||
STATUS_CONNECTED,
|
||||
|
@ -25,6 +37,8 @@ public:
|
|||
|
||||
static StreamPeerSSL* create();
|
||||
|
||||
static void load_certs_from_memory(const ByteArray& p_memory);
|
||||
static bool is_available();
|
||||
|
||||
StreamPeerSSL();
|
||||
};
|
||||
|
|
|
@ -17,23 +17,9 @@
|
|||
#include <string.h>
|
||||
|
||||
|
||||
Error ImageLoaderJPG::load_image(Image *p_image,FileAccess *f) {
|
||||
Error jpeg_load_image_from_buffer(Image *p_image,const uint8_t* p_buffer, int p_buffer_len) {
|
||||
|
||||
|
||||
DVector<uint8_t> src_image;
|
||||
int src_image_len = f->get_len();
|
||||
ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT);
|
||||
src_image.resize(src_image_len);
|
||||
|
||||
DVector<uint8_t>::Write w = src_image.write();
|
||||
|
||||
f->get_buffer(&w[0],src_image_len);
|
||||
|
||||
f->close();
|
||||
|
||||
|
||||
|
||||
jpgd::jpeg_decoder_mem_stream mem_stream(w.ptr(),src_image_len);
|
||||
jpgd::jpeg_decoder_mem_stream mem_stream(p_buffer,p_buffer_len);
|
||||
|
||||
jpgd::jpeg_decoder decoder(&mem_stream);
|
||||
|
||||
|
@ -85,14 +71,36 @@ Error ImageLoaderJPG::load_image(Image *p_image,FileAccess *f) {
|
|||
fmt=Image::FORMAT_RGBA;
|
||||
|
||||
dw = DVector<uint8_t>::Write();
|
||||
w = DVector<uint8_t>::Write();
|
||||
|
||||
p_image->create(image_width,image_height,0,fmt,data);
|
||||
|
||||
return OK;
|
||||
|
||||
}
|
||||
|
||||
|
||||
Error ImageLoaderJPG::load_image(Image *p_image,FileAccess *f) {
|
||||
|
||||
|
||||
DVector<uint8_t> src_image;
|
||||
int src_image_len = f->get_len();
|
||||
ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT);
|
||||
src_image.resize(src_image_len);
|
||||
|
||||
DVector<uint8_t>::Write w = src_image.write();
|
||||
|
||||
f->get_buffer(&w[0],src_image_len);
|
||||
|
||||
f->close();
|
||||
|
||||
|
||||
Error err = jpeg_load_image_from_buffer(p_image,w.ptr(),src_image_len);
|
||||
|
||||
w = DVector<uint8_t>::Write();
|
||||
|
||||
return err;
|
||||
|
||||
}
|
||||
|
||||
void ImageLoaderJPG::get_recognized_extensions(List<String> *p_extensions) const {
|
||||
|
||||
p_extensions->push_back("jpg");
|
||||
|
@ -100,9 +108,17 @@ void ImageLoaderJPG::get_recognized_extensions(List<String> *p_extensions) const
|
|||
}
|
||||
|
||||
|
||||
static Image _jpegd_mem_loader_func(const uint8_t* p_png,int p_size) {
|
||||
|
||||
Image img;
|
||||
Error err = jpeg_load_image_from_buffer(&img,p_png,p_size);
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
ImageLoaderJPG::ImageLoaderJPG() {
|
||||
|
||||
|
||||
Image::_jpg_mem_loader_func=_jpegd_mem_loader_func;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -532,8 +532,26 @@ StreamPeerSSL* StreamPeerOpenSSL::_create_func() {
|
|||
Vector<X509*> StreamPeerOpenSSL::certs;
|
||||
|
||||
|
||||
void StreamPeerOpenSSL::_load_certs(const ByteArray& p_array) {
|
||||
|
||||
ByteArray::Read r = p_array.read();
|
||||
BIO* mem = BIO_new(BIO_s_mem());
|
||||
BIO_puts(mem,(const char*)r.ptr());
|
||||
while(true) {
|
||||
X509*cert = PEM_read_bio_X509(mem, NULL, 0, NULL);
|
||||
if (!cert)
|
||||
break;
|
||||
certs.push_back(cert);
|
||||
}
|
||||
BIO_free(mem);
|
||||
}
|
||||
|
||||
void StreamPeerOpenSSL::initialize_ssl() {
|
||||
|
||||
available=true;
|
||||
|
||||
load_certs_func=_load_certs;
|
||||
|
||||
_create=_create_func;
|
||||
CRYPTO_malloc_init(); // Initialize malloc, free, etc for OpenSSL's use
|
||||
SSL_library_init(); // Initialize OpenSSL's SSL libraries
|
||||
|
@ -544,20 +562,24 @@ void StreamPeerOpenSSL::initialize_ssl() {
|
|||
Globals::get_singleton()->set_custom_property_info("ssl/certificates",PropertyInfo(Variant::STRING,"ssl/certificates",PROPERTY_HINT_FILE,"*.crt"));
|
||||
if (certs_path!="") {
|
||||
|
||||
Vector<uint8_t> data = FileAccess::get_file_as_array(certs_path);;
|
||||
if (data.size()) {
|
||||
data.push_back(0);
|
||||
BIO* mem = BIO_new(BIO_s_mem());
|
||||
BIO_puts(mem,(const char*) data.ptr());
|
||||
while(true) {
|
||||
X509*cert = PEM_read_bio_X509(mem, NULL, 0, NULL);
|
||||
if (!cert)
|
||||
break;
|
||||
certs.push_back(cert);
|
||||
|
||||
|
||||
FileAccess *f=FileAccess::open(certs_path,FileAccess::READ);
|
||||
if (f) {
|
||||
ByteArray arr;
|
||||
int flen = f->get_len();
|
||||
arr.resize(flen+1);
|
||||
{
|
||||
ByteArray::Write w = arr.write();
|
||||
f->get_buffer(w.ptr(),flen);
|
||||
w[flen]=0; //end f string
|
||||
}
|
||||
BIO_free(mem);
|
||||
|
||||
memdelete(f);
|
||||
|
||||
_load_certs(arr);
|
||||
print_line("Loaded certs from '"+certs_path+"': "+itos(certs.size()));
|
||||
}
|
||||
print_line("Loaded certs from '"+certs_path+"': "+itos(certs.size()));
|
||||
}
|
||||
String config_path =GLOBAL_DEF("ssl/config","");
|
||||
Globals::get_singleton()->set_custom_property_info("ssl/config",PropertyInfo(Variant::STRING,"ssl/config",PROPERTY_HINT_FILE,"*.cnf"));
|
||||
|
|
|
@ -54,6 +54,7 @@ private:
|
|||
|
||||
static Vector<X509*> certs;
|
||||
|
||||
static void _load_certs(const ByteArray& p_array);
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
#include "core/os/thread.h"
|
||||
#include "core/io/file_access_pack.h"
|
||||
#include "core/io/file_access_zip.h"
|
||||
#include "core/io/stream_peer_ssl.h"
|
||||
#include "translation.h"
|
||||
#include "version.h"
|
||||
#include "main/input_default.h"
|
||||
|
@ -635,6 +636,7 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas
|
|||
if (editor) {
|
||||
packed_data->set_disabled(true);
|
||||
globals->set_disable_platform_override(true);
|
||||
StreamPeerSSL::initialize_certs=false; //will be initialized by editor
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -31,7 +31,12 @@
|
|||
|
||||
Size2 PanelContainer::get_minimum_size() const {
|
||||
|
||||
Ref<StyleBox> style=get_stylebox("panel");
|
||||
Ref<StyleBox> style;
|
||||
|
||||
if (has_stylebox("panel"))
|
||||
style=get_stylebox("panel");
|
||||
else
|
||||
style=get_stylebox("panel","PanelContainer");
|
||||
|
||||
|
||||
Size2 ms;
|
||||
|
|
|
@ -35,7 +35,37 @@ bool ScrollContainer::clips_input() const {
|
|||
|
||||
Size2 ScrollContainer::get_minimum_size() const {
|
||||
|
||||
return Size2(1, 1);
|
||||
|
||||
Size2 min_size;
|
||||
|
||||
for(int i=0;i<get_child_count();i++) {
|
||||
|
||||
Control *c = get_child(i)->cast_to<Control>();
|
||||
if (!c)
|
||||
continue;
|
||||
if (c->is_set_as_toplevel())
|
||||
continue;
|
||||
if (c == h_scroll || c == v_scroll)
|
||||
continue;
|
||||
Size2 minsize = c->get_combined_minimum_size();
|
||||
|
||||
|
||||
if (!scroll_h) {
|
||||
min_size.x = MAX(min_size.x, minsize.x);
|
||||
}
|
||||
if (!scroll_v) {
|
||||
min_size.y = MAX(min_size.y, minsize.y);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (h_scroll->is_visible()) {
|
||||
min_size.y+=h_scroll->get_minimum_size().y;
|
||||
}
|
||||
if (v_scroll->is_visible()) {
|
||||
min_size.x+=v_scroll->get_minimum_size().x;
|
||||
}
|
||||
return min_size;
|
||||
};
|
||||
|
||||
|
||||
|
@ -179,6 +209,12 @@ void ScrollContainer::_notification(int p_what) {
|
|||
|
||||
child_max_size = Size2(0, 0);
|
||||
Size2 size = get_size();
|
||||
if (h_scroll->is_visible())
|
||||
size.y-=h_scroll->get_minimum_size().y;
|
||||
|
||||
if (v_scroll->is_visible())
|
||||
size.x-=h_scroll->get_minimum_size().x;
|
||||
|
||||
for(int i=0;i<get_child_count();i++) {
|
||||
|
||||
Control *c = get_child(i)->cast_to<Control>();
|
||||
|
|
|
@ -574,7 +574,14 @@ void TreeItem::set_custom_color(int p_column,const Color& p_color) {
|
|||
cells[p_column].color=p_color;
|
||||
_changed_notify(p_column);
|
||||
}
|
||||
Color TreeItem::get_custom_color(int p_column) const {
|
||||
|
||||
ERR_FAIL_INDEX_V( p_column, cells.size(), Color() );
|
||||
if (!cells[p_column].custom_color)
|
||||
return Color();
|
||||
return cells[p_column].color;
|
||||
|
||||
}
|
||||
void TreeItem::clear_custom_color(int p_column) {
|
||||
|
||||
ERR_FAIL_INDEX( p_column, cells.size() );
|
||||
|
|
|
@ -221,6 +221,7 @@ public:
|
|||
bool is_editable(int p_column);
|
||||
|
||||
void set_custom_color(int p_column,const Color& p_color);
|
||||
Color get_custom_color(int p_column) const;
|
||||
void clear_custom_color(int p_column);
|
||||
|
||||
void set_custom_bg_color(int p_column,const Color& p_color);
|
||||
|
|
|
@ -7,28 +7,22 @@ void HTTPRequest::_redirect_request(const String& p_new_url) {
|
|||
|
||||
Error HTTPRequest::_request() {
|
||||
|
||||
print_line("Requesting:\n\tURL: "+url+"\n\tString: "+request_string+"\n\tPort: "+itos(port)+"\n\tSSL: "+itos(use_ssl)+"\n\tValidate SSL: "+itos(validate_ssl));
|
||||
return client->connect(url,port,use_ssl,validate_ssl);
|
||||
}
|
||||
|
||||
Error HTTPRequest::request(const String& p_url, const Vector<String>& p_custom_headers, bool p_ssl_validate_domain) {
|
||||
|
||||
ERR_FAIL_COND_V(!is_inside_tree(),ERR_UNCONFIGURED);
|
||||
if ( requesting ) {
|
||||
ERR_EXPLAIN("HTTPRequest is processing a request. Wait for completion or cancel it before attempting a new one.");
|
||||
ERR_FAIL_V(ERR_BUSY);
|
||||
}
|
||||
Error HTTPRequest::_parse_url(const String& p_url) {
|
||||
|
||||
url=p_url;
|
||||
use_ssl=false;
|
||||
|
||||
request_string="";
|
||||
port=80;
|
||||
headers=p_custom_headers;
|
||||
request_sent=false;
|
||||
got_response=false;
|
||||
validate_ssl=p_ssl_validate_domain;
|
||||
body_len=-1;
|
||||
body.resize(0);
|
||||
downloaded=0;
|
||||
redirections=0;
|
||||
|
||||
print_line("1 url: "+url);
|
||||
|
@ -71,8 +65,23 @@ Error HTTPRequest::request(const String& p_url, const Vector<String>& p_custom_h
|
|||
|
||||
print_line("4 url: "+url);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
Error HTTPRequest::request(const String& p_url, const Vector<String>& p_custom_headers, bool p_ssl_validate_domain) {
|
||||
|
||||
ERR_FAIL_COND_V(!is_inside_tree(),ERR_UNCONFIGURED);
|
||||
if ( requesting ) {
|
||||
ERR_EXPLAIN("HTTPRequest is processing a request. Wait for completion or cancel it before attempting a new one.");
|
||||
ERR_FAIL_V(ERR_BUSY);
|
||||
}
|
||||
|
||||
Error err = _parse_url(p_url);
|
||||
validate_ssl=p_ssl_validate_domain;
|
||||
|
||||
bool has_user_agent=false;
|
||||
bool has_accept=false;
|
||||
headers=p_custom_headers;
|
||||
|
||||
for(int i=0;i<headers.size();i++) {
|
||||
|
||||
|
@ -91,7 +100,7 @@ Error HTTPRequest::request(const String& p_url, const Vector<String>& p_custom_h
|
|||
}
|
||||
|
||||
|
||||
Error err = _request();
|
||||
err = _request();
|
||||
|
||||
if (err==OK) {
|
||||
set_process(true);
|
||||
|
@ -112,16 +121,92 @@ void HTTPRequest::cancel_request() {
|
|||
set_process(false);
|
||||
}
|
||||
|
||||
if (file) {
|
||||
memdelete(file);
|
||||
file=NULL;
|
||||
}
|
||||
client->close();
|
||||
body.resize(0);
|
||||
//downloaded=0;
|
||||
got_response=false;
|
||||
response_code=-1;
|
||||
body_len=-1;
|
||||
//body_len=-1;
|
||||
request_sent=false;
|
||||
requesting=false;
|
||||
}
|
||||
|
||||
|
||||
bool HTTPRequest::_handle_response(bool *ret_value) {
|
||||
|
||||
if (!client->has_response()) {
|
||||
call_deferred("emit_signal","request_completed",RESULT_NO_RESPONSE,0,StringArray(),ByteArray());
|
||||
*ret_value=true;
|
||||
return true;
|
||||
}
|
||||
|
||||
got_response=true;
|
||||
response_code=client->get_response_code();
|
||||
List<String> rheaders;
|
||||
client->get_response_headers(&rheaders);
|
||||
response_headers.resize(0);
|
||||
downloaded=0;
|
||||
for (List<String>::Element *E=rheaders.front();E;E=E->next()) {
|
||||
print_line("HEADER: "+E->get());
|
||||
response_headers.push_back(E->get());
|
||||
}
|
||||
|
||||
if (response_code==301 || response_code==302) {
|
||||
//redirect
|
||||
if (max_redirects>=0 && redirections>=max_redirects) {
|
||||
|
||||
call_deferred("emit_signal","request_completed",RESULT_REDIRECT_LIMIT_REACHED,response_code,response_headers,ByteArray());
|
||||
*ret_value=true;
|
||||
return true;
|
||||
}
|
||||
|
||||
String new_request;
|
||||
|
||||
for (List<String>::Element *E=rheaders.front();E;E=E->next()) {
|
||||
if (E->get().findn("Location: ")!=-1) {
|
||||
new_request=E->get().substr(9,E->get().length()).strip_edges();
|
||||
}
|
||||
}
|
||||
|
||||
print_line("NEW LOCATION: "+new_request);
|
||||
|
||||
if (new_request!="") {
|
||||
//process redirect
|
||||
client->close();
|
||||
int new_redirs=redirections+1; //because _request() will clear it
|
||||
Error err;
|
||||
if (new_request.begins_with("http")) {
|
||||
//new url, request all again
|
||||
err=_parse_url(new_request);
|
||||
} else {
|
||||
request_string=new_request;
|
||||
}
|
||||
|
||||
err = _request();
|
||||
|
||||
print_line("new connection: "+itos(err));
|
||||
if (err==OK) {
|
||||
request_sent=false;
|
||||
got_response=false;
|
||||
body_len=-1;
|
||||
body.resize(0);
|
||||
downloaded=0;
|
||||
redirections=new_redirs;
|
||||
*ret_value=false;
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool HTTPRequest::_update_connection() {
|
||||
|
||||
switch( client->get_status() ) {
|
||||
|
@ -157,52 +242,10 @@ bool HTTPRequest::_update_connection() {
|
|||
|
||||
//no body
|
||||
|
||||
got_response=true;
|
||||
response_code=client->get_response_code();
|
||||
List<String> rheaders;
|
||||
client->get_response_headers(&rheaders);
|
||||
response_headers.resize(0);
|
||||
for (List<String>::Element *E=rheaders.front();E;E=E->next()) {
|
||||
print_line("HEADER: "+E->get());
|
||||
response_headers.push_back(E->get());
|
||||
}
|
||||
bool ret_value;
|
||||
|
||||
if (response_code==301) {
|
||||
//redirect
|
||||
if (max_redirects>=0 && redirections>=max_redirects) {
|
||||
|
||||
call_deferred("emit_signal","request_completed",RESULT_REDIRECT_LIMIT_REACHED,response_code,response_headers,ByteArray());
|
||||
return true;
|
||||
}
|
||||
|
||||
String new_request;
|
||||
|
||||
for (List<String>::Element *E=rheaders.front();E;E=E->next()) {
|
||||
if (E->get().findn("Location: ")!=-1) {
|
||||
new_request=E->get().substr(9,E->get().length()).strip_edges();
|
||||
}
|
||||
}
|
||||
|
||||
print_line("NEW LOCATION: "+new_request);
|
||||
|
||||
if (new_request!="") {
|
||||
//process redirect
|
||||
client->close();
|
||||
request_string=new_request;
|
||||
int new_redirs=redirections+1; //because _request() will clear it
|
||||
Error err = _request();
|
||||
print_line("new connection: "+itos(err));
|
||||
if (err==OK) {
|
||||
request_sent=false;
|
||||
got_response=false;
|
||||
body_len=-1;
|
||||
body.resize(0);
|
||||
redirections=new_redirs;
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_handle_response(&ret_value))
|
||||
return ret_value;
|
||||
|
||||
|
||||
call_deferred("emit_signal","request_completed",RESULT_SUCCESS,response_code,response_headers,ByteArray());
|
||||
|
@ -240,20 +283,12 @@ bool HTTPRequest::_update_connection() {
|
|||
case HTTPClient::STATUS_BODY: {
|
||||
|
||||
if (!got_response) {
|
||||
if (!client->has_response()) {
|
||||
call_deferred("emit_signal","request_completed",RESULT_NO_RESPONSE,0,StringArray(),ByteArray());
|
||||
return true;
|
||||
}
|
||||
|
||||
got_response=true;
|
||||
response_code=client->get_response_code();
|
||||
List<String> rheaders;
|
||||
client->get_response_headers(&rheaders);
|
||||
response_headers.resize(0);
|
||||
for (List<String>::Element *E=rheaders.front();E;E=E->next()) {
|
||||
print_line("HEADER: "+E->get());
|
||||
response_headers.push_back(E->get());
|
||||
}
|
||||
|
||||
bool ret_value;
|
||||
|
||||
if (_handle_response(&ret_value))
|
||||
return ret_value;
|
||||
|
||||
if (!client->is_response_chunked() && client->get_response_body_length()==0) {
|
||||
|
||||
|
@ -263,7 +298,7 @@ bool HTTPRequest::_update_connection() {
|
|||
|
||||
|
||||
if (client->is_response_chunked()) {
|
||||
body_len=-1;
|
||||
body_len=-1; //no body len because chunked, change your webserver configuration if you want body len
|
||||
} else {
|
||||
body_len=client->get_response_body_length();
|
||||
|
||||
|
@ -273,22 +308,41 @@ bool HTTPRequest::_update_connection() {
|
|||
}
|
||||
}
|
||||
|
||||
if (download_to_file!=String()) {
|
||||
file=FileAccess::open(download_to_file,FileAccess::WRITE);
|
||||
if (!file) {
|
||||
|
||||
call_deferred("emit_signal","request_completed",RESULT_DOWNLOAD_FILE_CANT_OPEN,response_code,response_headers,ByteArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//print_line("BODY: "+itos(body.size()));
|
||||
client->poll();
|
||||
|
||||
body.append_array(client->read_response_body_chunk());
|
||||
ByteArray chunk = client->read_response_body_chunk();
|
||||
downloaded+=chunk.size();
|
||||
|
||||
if (body_size_limit>=0 && body.size()>body_size_limit) {
|
||||
if (file) {
|
||||
ByteArray::Read r=chunk.read();
|
||||
file->store_buffer(r.ptr(),chunk.size());
|
||||
if (file->get_error()!=OK) {
|
||||
call_deferred("emit_signal","request_completed",RESULT_DOWNLOAD_FILE_WRITE_ERROR,response_code,response_headers,ByteArray());
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
body.append_array(chunk);
|
||||
}
|
||||
|
||||
if (body_size_limit>=0 && downloaded>body_size_limit) {
|
||||
call_deferred("emit_signal","request_completed",RESULT_BODY_SIZE_LIMIT_EXCEEDED,response_code,response_headers,ByteArray());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (body_len>=0) {
|
||||
|
||||
if (body.size()==body_len) {
|
||||
if (downloaded==body_len) {
|
||||
call_deferred("emit_signal","request_completed",RESULT_SUCCESS,response_code,response_headers,body);
|
||||
return true;
|
||||
}
|
||||
|
@ -351,6 +405,18 @@ int HTTPRequest::get_body_size_limit() const {
|
|||
return body_size_limit;
|
||||
}
|
||||
|
||||
|
||||
void HTTPRequest::set_download_file(const String& p_file) {
|
||||
|
||||
ERR_FAIL_COND( status!=HTTPClient::STATUS_DISCONNECTED );
|
||||
|
||||
download_to_file=p_file;
|
||||
}
|
||||
|
||||
String HTTPRequest::get_download_file() const {
|
||||
|
||||
return download_to_file;
|
||||
}
|
||||
HTTPClient::Status HTTPRequest::get_http_client_status() const {
|
||||
return client->get_status();
|
||||
}
|
||||
|
@ -365,6 +431,14 @@ int HTTPRequest::get_max_redirects() const{
|
|||
return max_redirects;
|
||||
}
|
||||
|
||||
int HTTPRequest::get_downloaded_bytes() const {
|
||||
|
||||
return downloaded;
|
||||
}
|
||||
int HTTPRequest::get_body_size() const{
|
||||
return body_len;
|
||||
}
|
||||
|
||||
|
||||
void HTTPRequest::_bind_methods() {
|
||||
|
||||
|
@ -382,6 +456,12 @@ void HTTPRequest::_bind_methods() {
|
|||
ObjectTypeDB::bind_method(_MD("set_max_redirects","amount"),&HTTPRequest::set_max_redirects);
|
||||
ObjectTypeDB::bind_method(_MD("get_max_redirects"),&HTTPRequest::get_max_redirects);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_download_file","path"),&HTTPRequest::set_download_file);
|
||||
ObjectTypeDB::bind_method(_MD("get_download_file"),&HTTPRequest::get_download_file);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("get_downloaded_bytes"),&HTTPRequest::get_downloaded_bytes);
|
||||
ObjectTypeDB::bind_method(_MD("get_body_size"),&HTTPRequest::get_body_size);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_redirect_request"),&HTTPRequest::_redirect_request);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"use_threads"),_SCS("set_use_threads"),_SCS("is_using_threads"));
|
||||
|
@ -401,6 +481,7 @@ void HTTPRequest::_bind_methods() {
|
|||
BIND_CONSTANT( RESULT_BODY_SIZE_LIMIT_EXCEEDED );
|
||||
BIND_CONSTANT( RESULT_REQUEST_FAILED );
|
||||
BIND_CONSTANT( RESULT_REDIRECT_LIMIT_REACHED );
|
||||
BIND_CONSTANT( RESULT_DOWNLOAD_FILE_WRITE_ERROR );
|
||||
|
||||
}
|
||||
|
||||
|
@ -413,14 +494,19 @@ HTTPRequest::HTTPRequest()
|
|||
max_redirects=8;
|
||||
body_len=-1;
|
||||
got_response=false;
|
||||
validate_ssl=false;
|
||||
validate_ssl=false;
|
||||
use_ssl=false;
|
||||
response_code=0;
|
||||
request_sent=false;
|
||||
client.instance();
|
||||
use_threads=false;
|
||||
body_size_limit=-1;
|
||||
file=NULL;
|
||||
status=HTTPClient::STATUS_DISCONNECTED;
|
||||
|
||||
}
|
||||
|
||||
HTTPRequest::~HTTPRequest() {
|
||||
if (file)
|
||||
memdelete(file);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "node.h"
|
||||
#include "io/http_client.h"
|
||||
#include "os/file_access.h"
|
||||
|
||||
class HTTPRequest : public Node {
|
||||
|
||||
|
@ -20,6 +21,8 @@ public:
|
|||
RESULT_NO_RESPONSE,
|
||||
RESULT_BODY_SIZE_LIMIT_EXCEEDED,
|
||||
RESULT_REQUEST_FAILED,
|
||||
RESULT_DOWNLOAD_FILE_CANT_OPEN,
|
||||
RESULT_DOWNLOAD_FILE_WRITE_ERROR,
|
||||
RESULT_REDIRECT_LIMIT_REACHED
|
||||
|
||||
};
|
||||
|
@ -44,8 +47,12 @@ private:
|
|||
int response_code;
|
||||
DVector<String> response_headers;
|
||||
|
||||
int body_len;
|
||||
String download_to_file;
|
||||
|
||||
FileAccess *file;
|
||||
|
||||
int body_len;
|
||||
int downloaded;
|
||||
int body_size_limit;
|
||||
|
||||
int redirections;
|
||||
|
@ -58,8 +65,12 @@ private:
|
|||
|
||||
void _redirect_request(const String& p_new_url);
|
||||
|
||||
bool _handle_response(bool *ret_value);
|
||||
|
||||
Error _parse_url(const String& p_url);
|
||||
Error _request();
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
|
@ -73,13 +84,20 @@ public:
|
|||
void set_use_threads(bool p_use);
|
||||
bool is_using_threads() const;
|
||||
|
||||
void set_download_file(const String& p_file);
|
||||
String get_download_file() const;
|
||||
|
||||
void set_body_size_limit(int p_bytes);
|
||||
int get_body_size_limit() const;
|
||||
|
||||
void set_max_redirects(int p_max);
|
||||
int get_max_redirects() const;
|
||||
|
||||
int get_downloaded_bytes() const;
|
||||
int get_body_size() const;
|
||||
|
||||
HTTPRequest();
|
||||
~HTTPRequest();
|
||||
};
|
||||
|
||||
#endif // HTTPREQUEST_H
|
||||
|
|
|
@ -890,7 +890,11 @@ void make_default_theme() {
|
|||
t->set_stylebox("border","ReferenceFrame", make_stylebox( reference_border_png,4,4,4,4) );
|
||||
t->set_stylebox("panelnc","Panel", ttnc );
|
||||
t->set_stylebox("panelf","Panel", tc_sb );
|
||||
t->set_stylebox("panel","PanelContainer", tc_sb );
|
||||
|
||||
Ref<StyleBoxTexture> sb_pc = make_stylebox( tab_container_bg_png,4,4,4,4,7,7,7,7);
|
||||
t->set_stylebox("panel","PanelContainer", sb_pc );
|
||||
|
||||
|
||||
|
||||
t->set_icon("minus","GraphEdit", make_icon(icon_zoom_less_png) );
|
||||
t->set_icon("reset","GraphEdit", make_icon(icon_zoom_reset_png) );
|
||||
|
|
4826
tools/certs/ca-certificates.crt
Normal file
4826
tools/certs/ca-certificates.crt
Normal file
File diff suppressed because it is too large
Load diff
|
@ -26,6 +26,31 @@ def make_doc_header(target,source,env):
|
|||
|
||||
|
||||
|
||||
def make_certs_header(target,source,env):
|
||||
|
||||
src = source[0].srcnode().abspath
|
||||
dst = target[0].srcnode().abspath
|
||||
f = open(src,"rb")
|
||||
g = open(dst,"wb")
|
||||
buf = f.read()
|
||||
decomp_size = len(buf)
|
||||
import zlib
|
||||
buf = zlib.compress(buf)
|
||||
|
||||
|
||||
g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
|
||||
g.write("#ifndef _CERTS_RAW_H\n")
|
||||
g.write("#define _CERTS_RAW_H\n")
|
||||
g.write("static const int _certs_compressed_size="+str(len(buf))+";\n")
|
||||
g.write("static const int _certs_uncompressed_size="+str(decomp_size)+";\n")
|
||||
g.write("static const unsigned char _certs_compressed[]={\n")
|
||||
for i in range(len(buf)):
|
||||
g.write(str(ord(buf[i]))+",\n")
|
||||
g.write("};\n")
|
||||
g.write("#endif")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -47,6 +72,9 @@ if (env["tools"]=="yes"):
|
|||
env.Depends("#tools/editor/doc_data_compressed.h","#doc/base/classes.xml")
|
||||
env.Command("#tools/editor/doc_data_compressed.h","#doc/base/classes.xml",make_doc_header)
|
||||
|
||||
env.Depends("#tools/editor/certs_compressed.h","#tools/certs/ca-certificates.crt")
|
||||
env.Command("#tools/editor/certs_compressed.h","#tools/certs/ca-certificates.crt",make_certs_header)
|
||||
|
||||
#make_doc_header(env.File("#tools/editor/doc_data_raw.h").srcnode().abspath,env.File("#doc/base/classes.xml").srcnode().abspath,env)
|
||||
|
||||
env.add_source_files(env.tool_sources,"*.cpp")
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "addon_editor_plugin.h"
|
||||
#include "editor_node.h"
|
||||
|
||||
#include "editor_settings.h"
|
||||
|
||||
|
||||
|
||||
|
@ -142,6 +142,7 @@ void EditorAddonLibraryItemDescription::set_image(int p_type,int p_index,const R
|
|||
case EditorAddonLibrary::IMAGE_QUEUE_ICON: {
|
||||
|
||||
item->call("set_image",p_type,p_index,p_image);
|
||||
icon=p_image;
|
||||
} break;
|
||||
case EditorAddonLibrary::IMAGE_QUEUE_THUMBNAIL: {
|
||||
|
||||
|
@ -166,12 +167,30 @@ void EditorAddonLibraryItemDescription::set_image(int p_type,int p_index,const R
|
|||
|
||||
void EditorAddonLibraryItemDescription::_bind_methods() {
|
||||
ObjectTypeDB::bind_method(_MD("set_image"),&EditorAddonLibraryItemDescription::set_image);
|
||||
ObjectTypeDB::bind_method(_MD("_link_click"),&EditorAddonLibraryItemDescription::_link_click);
|
||||
|
||||
}
|
||||
|
||||
void EditorAddonLibraryItemDescription::configure(const String& p_title,int p_asset_id,const String& p_category,int p_category_id,const String& p_author,int p_author_id,int p_rating,const String& p_cost,const String& p_description) {
|
||||
void EditorAddonLibraryItemDescription::_link_click(const String& p_url) {
|
||||
|
||||
ERR_FAIL_COND(!p_url.begins_with("http"));
|
||||
OS::get_singleton()->shell_open(p_url);
|
||||
}
|
||||
|
||||
void EditorAddonLibraryItemDescription::configure(const String& p_title,int p_asset_id,const String& p_category,int p_category_id,const String& p_author,int p_author_id,int p_rating,const String& p_cost,const String& p_version,const String& p_description,const String& p_download_url,const String& p_browse_url) {
|
||||
|
||||
asset_id=p_asset_id;
|
||||
title=p_title;
|
||||
download_url=p_download_url;
|
||||
item->configure(p_title,p_asset_id,p_category,p_category_id,p_author,p_author_id,p_rating,p_cost);
|
||||
description->parse_bbcode(p_description);
|
||||
description->clear();
|
||||
description->add_text("Version: "+p_version+"\n");
|
||||
description->add_text("Contents: ");
|
||||
description->push_meta(p_browse_url);
|
||||
description->add_text("View Files");
|
||||
description->pop();
|
||||
description->add_text("\nDescription:\n\n");
|
||||
description->append_bbcode(p_description);
|
||||
set_title(p_title);
|
||||
}
|
||||
|
||||
|
@ -215,6 +234,7 @@ EditorAddonLibraryItemDescription::EditorAddonLibraryItemDescription() {
|
|||
desc_bg->set_v_size_flags(SIZE_EXPAND_FILL);
|
||||
|
||||
description = memnew( RichTextLabel );
|
||||
description->connect("meta_clicked",this,"_link_click");
|
||||
//desc_vbox->add_child(description);
|
||||
desc_bg->add_child(description);
|
||||
desc_bg->add_style_override("panel",get_stylebox("normal","TextEdit"));
|
||||
|
@ -242,6 +262,205 @@ EditorAddonLibraryItemDescription::EditorAddonLibraryItemDescription() {
|
|||
|
||||
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void EditorAddonLibraryItemDownload::_http_download_completed(int p_status, int p_code, const StringArray& headers, const ByteArray& p_data) {
|
||||
|
||||
|
||||
String error_text;
|
||||
|
||||
switch(p_status) {
|
||||
|
||||
case HTTPRequest::RESULT_CANT_RESOLVE: {
|
||||
error_text=("Can't resolve hostname: "+host);
|
||||
status->set_text("Can't resolve.");
|
||||
} break;
|
||||
case HTTPRequest::RESULT_BODY_SIZE_LIMIT_EXCEEDED:
|
||||
case HTTPRequest::RESULT_CONNECTION_ERROR:
|
||||
case HTTPRequest::RESULT_CHUNKED_BODY_SIZE_MISMATCH: {
|
||||
error_text=("Connection error, please try again.");
|
||||
status->set_text("Can't connect.");
|
||||
} break;
|
||||
case HTTPRequest::RESULT_SSL_HANDSHAKE_ERROR:
|
||||
case HTTPRequest::RESULT_CANT_CONNECT: {
|
||||
error_text=("Can't connect to host: "+host);
|
||||
status->set_text("Can't connect.");
|
||||
} break;
|
||||
case HTTPRequest::RESULT_NO_RESPONSE: {
|
||||
error_text=("No response from host: "+host);
|
||||
status->set_text("No response.");
|
||||
} break;
|
||||
case HTTPRequest::RESULT_REQUEST_FAILED: {
|
||||
error_text=("Request failed, return code: "+itos(p_code));
|
||||
status->set_text("Req. Failed.");
|
||||
} break;
|
||||
case HTTPRequest::RESULT_REDIRECT_LIMIT_REACHED: {
|
||||
error_text=("Request failed, too many redirects");
|
||||
status->set_text("Redirect Loop.");
|
||||
} break;
|
||||
default: {
|
||||
if (p_code!=200) {
|
||||
error_text=("Request failed, return code: "+itos(p_code));
|
||||
status->set_text("Failed: "+itos(p_code));
|
||||
} else {
|
||||
|
||||
//all good
|
||||
}
|
||||
} break;
|
||||
|
||||
}
|
||||
|
||||
if (error_text!=String()) {
|
||||
download_error->set_text("Asset Download Error:\n"+error_text);
|
||||
download_error->popup_centered_minsize();
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
progress->set_max( download->get_body_size() );
|
||||
progress->set_val(download->get_downloaded_bytes());
|
||||
|
||||
print_line("max: "+itos(download->get_body_size())+" bytes: "+itos(download->get_downloaded_bytes()));
|
||||
install->set_disabled(false);
|
||||
|
||||
status->set_text("Success!");
|
||||
set_process(false);
|
||||
}
|
||||
|
||||
|
||||
void EditorAddonLibraryItemDownload::configure(const String& p_title,int p_asset_id,const Ref<Texture>& p_preview, const String& p_download_url) {
|
||||
|
||||
title->set_text(p_title);
|
||||
icon->set_texture(p_preview);
|
||||
asset_id=p_asset_id;
|
||||
if (!p_preview.is_valid())
|
||||
icon->set_texture(get_icon("GodotAssetDefault","EditorIcons"));
|
||||
|
||||
host=p_download_url;
|
||||
set_process(true);
|
||||
download->set_download_file(EditorSettings::get_singleton()->get_settings_path().plus_file("tmp").plus_file("tmp_asset_"+itos(p_asset_id))+".zip");
|
||||
Error err = download->request(p_download_url);
|
||||
ERR_FAIL_COND(err!=OK);
|
||||
asset_installer->connect("confirmed",this,"_close");
|
||||
dismiss->set_normal_texture(get_icon("Close","EditorIcons"));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void EditorAddonLibraryItemDownload::_notification(int p_what) {
|
||||
|
||||
if (p_what==NOTIFICATION_PROCESS) {
|
||||
|
||||
progress->set_max( download->get_body_size() );
|
||||
progress->set_val(download->get_downloaded_bytes());
|
||||
|
||||
int cstatus = download->get_http_client_status();
|
||||
if (cstatus!=prev_status) {
|
||||
switch(cstatus) {
|
||||
|
||||
case HTTPClient::STATUS_RESOLVING: {
|
||||
status->set_text("Resolving..");
|
||||
} break;
|
||||
case HTTPClient::STATUS_CONNECTING: {
|
||||
status->set_text("Connecting..");
|
||||
} break;
|
||||
case HTTPClient::STATUS_REQUESTING: {
|
||||
status->set_text("Requesting..");
|
||||
} break;
|
||||
case HTTPClient::STATUS_BODY: {
|
||||
status->set_text("Downloading..");
|
||||
} break;
|
||||
default: {}
|
||||
}
|
||||
prev_status=cstatus;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
void EditorAddonLibraryItemDownload::_close() {
|
||||
|
||||
DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
|
||||
da->remove(download->get_download_file()); //clean up removed file
|
||||
memdelete(da);
|
||||
queue_delete();
|
||||
}
|
||||
|
||||
void EditorAddonLibraryItemDownload::_install() {
|
||||
|
||||
String file = download->get_download_file();
|
||||
asset_installer->open(file,1);
|
||||
}
|
||||
|
||||
void EditorAddonLibraryItemDownload::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method("_http_download_completed",&EditorAddonLibraryItemDownload::_http_download_completed);
|
||||
ObjectTypeDB::bind_method("_install",&EditorAddonLibraryItemDownload::_install);
|
||||
ObjectTypeDB::bind_method("_close",&EditorAddonLibraryItemDownload::_close);
|
||||
|
||||
}
|
||||
|
||||
EditorAddonLibraryItemDownload::EditorAddonLibraryItemDownload() {
|
||||
|
||||
HBoxContainer *hb = memnew( HBoxContainer);
|
||||
add_child(hb);
|
||||
icon = memnew( TextureFrame );
|
||||
hb->add_child(icon);
|
||||
|
||||
VBoxContainer *vb = memnew( VBoxContainer );
|
||||
hb->add_child(vb);
|
||||
vb->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
|
||||
HBoxContainer *title_hb = memnew( HBoxContainer);
|
||||
vb->add_child(title_hb);
|
||||
title = memnew( Label );
|
||||
title_hb->add_child(title);
|
||||
title->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
|
||||
dismiss = memnew( TextureButton );
|
||||
dismiss->connect("pressed",this,"_close");
|
||||
title_hb->add_child(dismiss);
|
||||
|
||||
title->set_clip_text(true);
|
||||
|
||||
vb->add_spacer();
|
||||
|
||||
status = memnew (Label("Idle"));
|
||||
vb->add_child(status);
|
||||
status->add_color_override("font_color", Color(0.5,0.5,0.5) );
|
||||
progress = memnew( ProgressBar );
|
||||
vb->add_child(progress);
|
||||
|
||||
|
||||
|
||||
HBoxContainer *hb2 = memnew( HBoxContainer );
|
||||
vb->add_child(hb2);
|
||||
hb2->add_spacer();
|
||||
|
||||
install = memnew( Button );
|
||||
install->set_text("Install");
|
||||
install->set_disabled(true);
|
||||
install->connect("pressed",this,"_install");
|
||||
|
||||
hb2->add_child(install);
|
||||
set_custom_minimum_size(Size2(250,0));
|
||||
|
||||
download = memnew( HTTPRequest );
|
||||
add_child(download);
|
||||
download->connect("request_completed",this,"_http_download_completed");
|
||||
|
||||
download_error = memnew( AcceptDialog );
|
||||
add_child(download_error);
|
||||
download_error->set_title("Download Error");
|
||||
|
||||
asset_installer = memnew( EditorAssetInstaller );
|
||||
add_child(asset_installer);
|
||||
|
||||
prev_status=-1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -261,7 +480,7 @@ void EditorAddonLibrary::_notification(int p_what) {
|
|||
HTTPClient::Status s = request->get_http_client_status();
|
||||
bool visible = s!=HTTPClient::STATUS_DISCONNECTED;
|
||||
|
||||
if (visible !=load_status->is_visible()) {
|
||||
if (visible != !load_status->is_hidden()) {
|
||||
load_status->set_hidden(!visible);
|
||||
}
|
||||
|
||||
|
@ -280,14 +499,41 @@ void EditorAddonLibrary::_notification(int p_what) {
|
|||
case HTTPClient::STATUS_BODY: {
|
||||
load_status->set_val(0.4);
|
||||
} break;
|
||||
default: {}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool no_downloads = downloads_hb->get_child_count()==0;
|
||||
if (no_downloads != downloads_scroll->is_hidden()) {
|
||||
downloads_scroll->set_hidden(no_downloads);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void EditorAddonLibrary::_install_asset() {
|
||||
|
||||
ERR_FAIL_COND(!description);
|
||||
|
||||
for(int i=0;i<downloads_hb->get_child_count();i++) {
|
||||
|
||||
EditorAddonLibraryItemDownload *d = downloads_hb->get_child(i)->cast_to<EditorAddonLibraryItemDownload>();
|
||||
if (d && d->get_asset_id() == description->get_asset_id()) {
|
||||
|
||||
EditorNode::get_singleton()->show_warning("Download for this asset is already in progress!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EditorAddonLibraryItemDownload * download = memnew( EditorAddonLibraryItemDownload );
|
||||
downloads_hb->add_child(download);
|
||||
download->configure(description->get_title(),description->get_asset_id(),description->get_preview_icon(),description->get_download_url());
|
||||
|
||||
}
|
||||
|
||||
const char* EditorAddonLibrary::sort_key[SORT_MAX]={
|
||||
"rating",
|
||||
"downloads",
|
||||
|
@ -708,15 +954,23 @@ void EditorAddonLibrary::_http_request_completed(int p_status, int p_code, const
|
|||
|
||||
Dictionary r = d["info"];
|
||||
|
||||
r["download_url"]="https://github.com/reduz/godot-test-addon/archive/master.zip";
|
||||
r["browse_url"]="https://github.com/reduz/godot-test-addon";
|
||||
r["version"]="1.1";
|
||||
|
||||
ERR_FAIL_COND(!r.has("title"));
|
||||
ERR_FAIL_COND(!r.has("asset_id"));
|
||||
ERR_FAIL_COND(!r.has("author"));
|
||||
ERR_FAIL_COND(!r.has("author_id"));
|
||||
ERR_FAIL_COND(!r.has("version"));
|
||||
ERR_FAIL_COND(!r.has("category"));
|
||||
ERR_FAIL_COND(!r.has("category_id"));
|
||||
ERR_FAIL_COND(!r.has("rating"));
|
||||
ERR_FAIL_COND(!r.has("cost"));
|
||||
ERR_FAIL_COND(!r.has("description"));
|
||||
ERR_FAIL_COND(!r.has("download_url"));
|
||||
ERR_FAIL_COND(!r.has("browse_url"));
|
||||
|
||||
|
||||
if (description) {
|
||||
memdelete(description);
|
||||
|
@ -725,8 +979,9 @@ void EditorAddonLibrary::_http_request_completed(int p_status, int p_code, const
|
|||
description = memnew( EditorAddonLibraryItemDescription );
|
||||
add_child(description);
|
||||
description->popup_centered_minsize();
|
||||
description->connect("confirmed",this,"_install_asset");
|
||||
|
||||
description->configure(r["title"],r["asset_id"],r["category"],r["category_id"],r["author"],r["author_id"],r["rating"],r["cost"],r["description"]);
|
||||
description->configure(r["title"],r["asset_id"],r["category"],r["category_id"],r["author"],r["author_id"],r["rating"],r["cost"],r["version"],r["description"],r["download_url"],r["browse_url"]);
|
||||
/*item->connect("asset_selected",this,"_select_asset");
|
||||
item->connect("author_selected",this,"_select_author");
|
||||
item->connect("category_selected",this,"_category_selected");*/
|
||||
|
@ -764,6 +1019,34 @@ void EditorAddonLibrary::_http_request_completed(int p_status, int p_code, const
|
|||
|
||||
}
|
||||
|
||||
|
||||
void EditorAddonLibrary::_asset_file_selected(const String& p_file) {
|
||||
|
||||
if (asset_installer) {
|
||||
memdelete( asset_installer );
|
||||
asset_installer=NULL;
|
||||
}
|
||||
|
||||
asset_installer = memnew( EditorAssetInstaller );
|
||||
add_child(asset_installer);
|
||||
asset_installer->open(p_file);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void EditorAddonLibrary::_asset_open() {
|
||||
|
||||
asset_open->popup_centered_ratio();
|
||||
}
|
||||
|
||||
void EditorAddonLibrary::_manage_plugins() {
|
||||
|
||||
ProjectSettings::get_singleton()->popup_project_settings();
|
||||
ProjectSettings::get_singleton()->set_plugins_page();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void EditorAddonLibrary::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method("_http_request_completed",&EditorAddonLibrary::_http_request_completed);
|
||||
|
@ -772,40 +1055,35 @@ void EditorAddonLibrary::_bind_methods() {
|
|||
ObjectTypeDB::bind_method("_select_category",&EditorAddonLibrary::_select_category);
|
||||
ObjectTypeDB::bind_method("_image_request_completed",&EditorAddonLibrary::_image_request_completed);
|
||||
ObjectTypeDB::bind_method("_search",&EditorAddonLibrary::_search,DEFVAL(0));
|
||||
ObjectTypeDB::bind_method("_install_asset",&EditorAddonLibrary::_install_asset);
|
||||
ObjectTypeDB::bind_method("_manage_plugins",&EditorAddonLibrary::_manage_plugins);
|
||||
ObjectTypeDB::bind_method("_asset_open",&EditorAddonLibrary::_asset_open);
|
||||
ObjectTypeDB::bind_method("_asset_file_selected",&EditorAddonLibrary::_asset_file_selected);
|
||||
|
||||
}
|
||||
|
||||
EditorAddonLibrary::EditorAddonLibrary() {
|
||||
|
||||
tabs = memnew( TabContainer );
|
||||
tabs->set_v_size_flags(SIZE_EXPAND_FILL);
|
||||
add_child(tabs);
|
||||
|
||||
installed = memnew( EditorPluginSettings );
|
||||
installed->set_name("Installed");
|
||||
tabs->add_child(installed);
|
||||
|
||||
Ref<StyleBoxEmpty> border;
|
||||
border.instance();
|
||||
border->set_default_margin(MARGIN_LEFT,15);
|
||||
border->set_default_margin(MARGIN_RIGHT,15);
|
||||
border->set_default_margin(MARGIN_BOTTOM,15);
|
||||
border->set_default_margin(MARGIN_BOTTOM,5);
|
||||
border->set_default_margin(MARGIN_TOP,5);
|
||||
|
||||
PanelContainer *margin_panel = memnew( PanelContainer );
|
||||
|
||||
margin_panel->set_name("Online");
|
||||
margin_panel->add_style_override("panel",border);
|
||||
tabs->add_child(margin_panel);
|
||||
add_style_override("panel",border);
|
||||
|
||||
VBoxContainer *library_main = memnew( VBoxContainer );
|
||||
|
||||
margin_panel->add_child(library_main);
|
||||
add_child(library_main);
|
||||
|
||||
HBoxContainer *search_hb = memnew( HBoxContainer );
|
||||
|
||||
library_main->add_child(search_hb);
|
||||
library_main->add_constant_override("separation",20);
|
||||
library_main->add_constant_override("separation",10);
|
||||
|
||||
|
||||
|
||||
search_hb->add_child( memnew( Label("Search: ")));
|
||||
filter =memnew( LineEdit );
|
||||
|
@ -815,6 +1093,20 @@ EditorAddonLibrary::EditorAddonLibrary() {
|
|||
search = memnew( Button("Search"));
|
||||
search->connect("pressed",this,"_search");
|
||||
search_hb->add_child(search);
|
||||
|
||||
search_hb->add_child(memnew( VSeparator ));
|
||||
|
||||
Button * open_asset = memnew( Button );
|
||||
open_asset->set_text("Import");
|
||||
search_hb->add_child(open_asset);
|
||||
open_asset->connect("pressed",this,"_asset_open");
|
||||
|
||||
Button * plugins = memnew( Button );
|
||||
plugins->set_text("Plugins");
|
||||
search_hb->add_child(plugins);
|
||||
plugins->connect("pressed",this,"_manage_plugins");
|
||||
|
||||
|
||||
library_vb->add_child(search_hb);
|
||||
|
||||
HBoxContainer *search_hb2 = memnew( HBoxContainer );
|
||||
|
@ -907,6 +1199,7 @@ EditorAddonLibrary::EditorAddonLibrary() {
|
|||
add_child(request);
|
||||
request->connect("request_completed",this,"_http_request_completed");
|
||||
|
||||
|
||||
last_queue_id=0;
|
||||
|
||||
library_vb->add_constant_override("separation",20);
|
||||
|
@ -928,6 +1221,24 @@ EditorAddonLibrary::EditorAddonLibrary() {
|
|||
//host="http://localhost:8000";
|
||||
host="http://godotengine.org/addonlib";
|
||||
set_process(true);
|
||||
|
||||
downloads_scroll = memnew( ScrollContainer );
|
||||
downloads_scroll->set_enable_h_scroll(true);
|
||||
downloads_scroll->set_enable_v_scroll(false);
|
||||
library_main->add_child(downloads_scroll);
|
||||
downloads_hb = memnew( HBoxContainer );
|
||||
downloads_scroll->add_child(downloads_hb);
|
||||
|
||||
asset_open = memnew( EditorFileDialog );
|
||||
|
||||
asset_open->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
|
||||
asset_open->add_filter("*.zip ; Assets ZIP File");
|
||||
asset_open->set_mode(EditorFileDialog::MODE_OPEN_FILE);
|
||||
add_child(asset_open);
|
||||
asset_open->connect("file_selected",this,"_asset_file_selected");
|
||||
|
||||
asset_installer=NULL;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "editor_plugin_settings.h"
|
||||
|
||||
#include "scene/main/http_request.h"
|
||||
#include "editor_asset_installer.h"
|
||||
|
||||
class EditorAssetLibraryItem : public PanelContainer {
|
||||
|
||||
|
@ -77,25 +78,79 @@ class EditorAddonLibraryItemDescription : public ConfirmationDialog {
|
|||
|
||||
void set_image(int p_type,int p_index,const Ref<Texture>& p_image);
|
||||
|
||||
int asset_id;
|
||||
String download_url;
|
||||
String title;
|
||||
Ref<Texture> icon;
|
||||
|
||||
void _link_click(const String& p_url);
|
||||
protected:
|
||||
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void configure(const String& p_title,int p_asset_id,const String& p_category,int p_category_id,const String& p_author,int p_author_id,int p_rating,const String& p_cost,const String& p_description);
|
||||
void configure(const String& p_title,int p_asset_id,const String& p_category,int p_category_id,const String& p_author,int p_author_id,int p_rating,const String& p_cost,const String& p_version,const String& p_description,const String& p_download_url,const String& p_browse_url);
|
||||
void add_preview(int p_id, bool p_video,const String& p_url);
|
||||
|
||||
String get_title() { return title; }
|
||||
Ref<Texture> get_preview_icon() { return icon; }
|
||||
String get_download_url() { return download_url; }
|
||||
int get_asset_id() { return asset_id; }
|
||||
EditorAddonLibraryItemDescription();
|
||||
|
||||
};
|
||||
|
||||
class EditorAddonLibrary : public VBoxContainer {
|
||||
OBJ_TYPE(EditorAddonLibrary,VBoxContainer);
|
||||
class EditorAddonLibraryItemDownload : public PanelContainer {
|
||||
|
||||
OBJ_TYPE(EditorAddonLibraryItemDownload, PanelContainer);
|
||||
|
||||
|
||||
TextureFrame *icon;
|
||||
Label* title;
|
||||
ProgressBar *progress;
|
||||
Button *install;
|
||||
TextureButton *dismiss;
|
||||
|
||||
AcceptDialog *download_error;
|
||||
HTTPRequest *download;
|
||||
String host;
|
||||
Label *status;
|
||||
|
||||
int prev_status;
|
||||
|
||||
int asset_id;
|
||||
|
||||
EditorAssetInstaller *asset_installer;
|
||||
|
||||
void _close();
|
||||
void _install();
|
||||
void _http_download_completed(int p_status, int p_code, const StringArray& headers, const ByteArray& p_data);
|
||||
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
int get_asset_id() { return asset_id; }
|
||||
void configure(const String& p_title,int p_asset_id,const Ref<Texture>& p_preview, const String& p_download_url);
|
||||
EditorAddonLibraryItemDownload();
|
||||
|
||||
};
|
||||
|
||||
class EditorAddonLibrary : public PanelContainer {
|
||||
OBJ_TYPE(EditorAddonLibrary,PanelContainer);
|
||||
|
||||
String host;
|
||||
|
||||
TabContainer *tabs;
|
||||
EditorPluginSettings *installed;
|
||||
EditorFileDialog *asset_open;
|
||||
EditorAssetInstaller *asset_installer;
|
||||
|
||||
|
||||
void _asset_open();
|
||||
void _asset_file_selected(const String& p_file);
|
||||
|
||||
|
||||
ScrollContainer *library_scroll;
|
||||
VBoxContainer *library_vb;
|
||||
LineEdit *filter;
|
||||
|
@ -116,6 +171,7 @@ class EditorAddonLibrary : public VBoxContainer {
|
|||
|
||||
HTTPRequest *request;
|
||||
|
||||
|
||||
enum SortOrder {
|
||||
SORT_RATING,
|
||||
SORT_DOWNLOADS,
|
||||
|
@ -155,6 +211,7 @@ class EditorAddonLibrary : public VBoxContainer {
|
|||
|
||||
|
||||
void _image_request_completed(int p_status, int p_code, const StringArray& headers, const ByteArray& p_data, int p_queue_id);
|
||||
|
||||
void _request_image(ObjectID p_for,int p_asset_id,ImageType p_type,int p_image_index);
|
||||
void _update_image_queue();
|
||||
|
||||
|
@ -174,13 +231,24 @@ class EditorAddonLibrary : public VBoxContainer {
|
|||
|
||||
RequestType requesting;
|
||||
|
||||
|
||||
ScrollContainer *downloads_scroll;
|
||||
HBoxContainer *downloads_hb;
|
||||
|
||||
|
||||
|
||||
void _install_asset();
|
||||
|
||||
void _select_author(int p_id);
|
||||
void _select_category(int p_id);
|
||||
void _select_asset(int p_id);
|
||||
|
||||
void _manage_plugins();
|
||||
|
||||
void _search(int p_page=0);
|
||||
void _api_request(const String& p_request, const String &p_arguments="");
|
||||
void _http_request_completed(int p_status, int p_code, const StringArray& headers, const ByteArray& p_data);
|
||||
void _http_download_completed(int p_status, int p_code, const StringArray& headers, const ByteArray& p_data);
|
||||
|
||||
friend class EditorAddonLibraryItemDescription;
|
||||
friend class EditorAssetLibraryItem;
|
||||
|
|
327
tools/editor/editor_asset_installer.cpp
Normal file
327
tools/editor/editor_asset_installer.cpp
Normal file
|
@ -0,0 +1,327 @@
|
|||
#include "editor_asset_installer.h"
|
||||
#include "io/zip_io.h"
|
||||
#include "os/dir_access.h"
|
||||
#include "os/file_access.h"
|
||||
#include "editor_node.h"
|
||||
void EditorAssetInstaller::_update_subitems(TreeItem* p_item,bool p_check,bool p_first) {
|
||||
|
||||
|
||||
if (p_check) {
|
||||
if (p_item->get_custom_color(0)==Color()) {
|
||||
p_item->set_checked(0,true);
|
||||
}
|
||||
} else {
|
||||
p_item->set_checked(0,false);
|
||||
|
||||
}
|
||||
|
||||
if (p_item->get_children()) {
|
||||
_update_subitems(p_item->get_children(),p_check);
|
||||
}
|
||||
|
||||
if (!p_first && p_item->get_next()) {
|
||||
_update_subitems(p_item->get_next(),p_check);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void EditorAssetInstaller::_item_edited() {
|
||||
|
||||
|
||||
if (updating)
|
||||
return;
|
||||
|
||||
TreeItem *item = tree->get_edited();
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
|
||||
String path=item->get_metadata(0);
|
||||
|
||||
updating=true;
|
||||
if (path==String()) { //a dir
|
||||
_update_subitems(item,item->is_checked(0),true);
|
||||
}
|
||||
|
||||
if (item->is_checked(0)) {
|
||||
while(item) {
|
||||
item->set_checked(0,true);
|
||||
item=item->get_parent();
|
||||
}
|
||||
|
||||
}
|
||||
updating=false;
|
||||
|
||||
}
|
||||
|
||||
void EditorAssetInstaller::open(const String& p_path,int p_depth) {
|
||||
|
||||
|
||||
package_path=p_path;
|
||||
Set<String> files_sorted;
|
||||
|
||||
FileAccess *src_f=NULL;
|
||||
zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
|
||||
|
||||
unzFile pkg = unzOpen2(p_path.utf8().get_data(), &io);
|
||||
if (!pkg) {
|
||||
|
||||
error->set_text("Error opening package file, not in zip format.");
|
||||
return;
|
||||
}
|
||||
|
||||
int ret = unzGoToFirstFile(pkg);
|
||||
|
||||
|
||||
while(ret==UNZ_OK) {
|
||||
|
||||
//get filename
|
||||
unz_file_info info;
|
||||
char fname[16384];
|
||||
ret = unzGetCurrentFileInfo(pkg,&info,fname,16384,NULL,0,NULL,0);
|
||||
|
||||
String name=fname;
|
||||
files_sorted.insert(name);
|
||||
|
||||
ret = unzGoToNextFile(pkg);
|
||||
}
|
||||
|
||||
|
||||
Map<String,Ref<Texture> > extension_guess;
|
||||
{
|
||||
extension_guess["png"]=get_icon("Texture","EditorIcons");
|
||||
extension_guess["jpg"]=get_icon("Texture","EditorIcons");
|
||||
extension_guess["tex"]=get_icon("Texture","EditorIcons");
|
||||
extension_guess["atex"]=get_icon("Texture","EditorIcons");
|
||||
extension_guess["dds"]=get_icon("Texture","EditorIcons");
|
||||
extension_guess["scn"]=get_icon("PackedScene","EditorIcons");
|
||||
extension_guess["tscn"]=get_icon("PackedScene","EditorIcons");
|
||||
extension_guess["xml"]=get_icon("PackedScene","EditorIcons");
|
||||
extension_guess["xscn"]=get_icon("PackedScene","EditorIcons");
|
||||
extension_guess["mtl"]=get_icon("Material","EditorIcons");
|
||||
extension_guess["shd"]=get_icon("Shader","EditorIcons");
|
||||
extension_guess["gd"]=get_icon("GDScript","EditorIcons");
|
||||
}
|
||||
|
||||
Ref<Texture> generic_extension = get_icon("Object","EditorIcons");
|
||||
|
||||
|
||||
unzClose(pkg);
|
||||
|
||||
updating=true;
|
||||
tree->clear();
|
||||
TreeItem *root=tree->create_item();
|
||||
root->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
|
||||
root->set_checked(0,true);
|
||||
root->set_icon(0,get_icon("folder","FileDialog"));
|
||||
root->set_text(0,"res://");
|
||||
root->set_editable(0,true);
|
||||
Map<String,TreeItem*> dir_map;
|
||||
|
||||
for(Set<String>::Element *E=files_sorted.front();E;E=E->next()) {
|
||||
|
||||
String path = E->get();
|
||||
int depth=p_depth;
|
||||
bool skip=false;
|
||||
while(depth>0) {
|
||||
int pp = path.find("/");
|
||||
if (pp==-1) {
|
||||
skip=true;
|
||||
break;
|
||||
}
|
||||
path=path.substr(pp+1,path.length());
|
||||
depth--;
|
||||
}
|
||||
|
||||
if (skip || path==String())
|
||||
continue;
|
||||
|
||||
bool isdir=false;
|
||||
|
||||
if (path.ends_with("/")) {
|
||||
//a directory
|
||||
path=path.substr(0,path.length()-1);
|
||||
isdir=true;
|
||||
}
|
||||
|
||||
int pp = path.find_last("/");
|
||||
|
||||
|
||||
TreeItem *parent;
|
||||
if (pp==-1) {
|
||||
parent=root;
|
||||
} else {
|
||||
String ppath=path.substr(0,pp);
|
||||
print_line("PPATH IS: "+ppath);
|
||||
ERR_CONTINUE(!dir_map.has(ppath));
|
||||
parent=dir_map[ppath];
|
||||
|
||||
}
|
||||
|
||||
TreeItem *ti = tree->create_item(parent);
|
||||
ti->set_cell_mode(0,TreeItem::CELL_MODE_CHECK);
|
||||
ti->set_checked(0,true);
|
||||
ti->set_editable(0,true);
|
||||
if (isdir) {
|
||||
dir_map[path]=ti;
|
||||
ti->set_text(0,path.get_file()+"/");
|
||||
ti->set_icon(0,get_icon("folder","FileDialog"));
|
||||
} else {
|
||||
String file = path.get_file();
|
||||
String extension = file.extension().to_lower();
|
||||
if (extension_guess.has(extension)) {
|
||||
ti->set_icon(0,extension_guess[extension]);
|
||||
} else {
|
||||
ti->set_icon(0,generic_extension);
|
||||
}
|
||||
ti->set_text(0,file);
|
||||
|
||||
|
||||
String res_path = "res://"+path;
|
||||
if (FileAccess::exists(res_path)) {
|
||||
ti->set_custom_color(0,Color(1,0.3,0.2));
|
||||
ti->set_tooltip(0,res_path+" (Already Exists)");
|
||||
ti->set_checked(0,false);
|
||||
} else {
|
||||
ti->set_tooltip(0,res_path);
|
||||
|
||||
}
|
||||
|
||||
ti->set_metadata(0,res_path);
|
||||
|
||||
}
|
||||
|
||||
status_map[E->get()]=ti;
|
||||
|
||||
|
||||
|
||||
}
|
||||
popup_centered_ratio();
|
||||
updating=false;
|
||||
|
||||
}
|
||||
|
||||
void EditorAssetInstaller::ok_pressed() {
|
||||
|
||||
FileAccess *src_f=NULL;
|
||||
zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
|
||||
|
||||
unzFile pkg = unzOpen2(package_path.utf8().get_data(), &io);
|
||||
if (!pkg) {
|
||||
|
||||
error->set_text("Error opening package file, not in zip format.");
|
||||
return;
|
||||
}
|
||||
|
||||
int ret = unzGoToFirstFile(pkg);
|
||||
|
||||
Vector<String> failed_files;
|
||||
|
||||
ProgressDialog::get_singleton()->add_task("uncompress","Uncompressing Assets",status_map.size());
|
||||
|
||||
int idx=0;
|
||||
while(ret==UNZ_OK) {
|
||||
|
||||
//get filename
|
||||
unz_file_info info;
|
||||
char fname[16384];
|
||||
ret = unzGetCurrentFileInfo(pkg,&info,fname,16384,NULL,0,NULL,0);
|
||||
|
||||
String name=fname;
|
||||
|
||||
if (status_map.has(name) && status_map[name]->is_checked(0)) {
|
||||
|
||||
String path = status_map[name]->get_metadata(0);
|
||||
if (path==String()) { // a dir
|
||||
|
||||
String dirpath;
|
||||
TreeItem *t = status_map[name];
|
||||
while(t) {
|
||||
dirpath=t->get_text(0)+dirpath;
|
||||
t=t->get_parent();
|
||||
}
|
||||
|
||||
if (dirpath.ends_with("/")) {
|
||||
dirpath=dirpath.substr(0,dirpath.length()-1);
|
||||
}
|
||||
|
||||
DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
|
||||
da->make_dir(dirpath);
|
||||
memdelete(da);
|
||||
|
||||
} else {
|
||||
|
||||
Vector<uint8_t> data;
|
||||
data.resize(info.uncompressed_size);
|
||||
|
||||
//read
|
||||
unzOpenCurrentFile(pkg);
|
||||
unzReadCurrentFile(pkg,data.ptr(),data.size());
|
||||
unzCloseCurrentFile(pkg);
|
||||
|
||||
FileAccess *f=FileAccess::open(path,FileAccess::WRITE);
|
||||
if (f) {
|
||||
f->store_buffer(data.ptr(),data.size());
|
||||
memdelete(f);
|
||||
} else {
|
||||
failed_files.push_back(path);
|
||||
}
|
||||
|
||||
ProgressDialog::get_singleton()->task_step("uncompress",path,idx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
idx++;
|
||||
ret = unzGoToNextFile(pkg);
|
||||
}
|
||||
|
||||
ProgressDialog::get_singleton()->end_task("uncompress");
|
||||
unzClose(pkg);
|
||||
|
||||
if (failed_files.size()) {
|
||||
String msg="The following files failed extraction from package:\n\n";
|
||||
for(int i=0;i<failed_files.size();i++) {
|
||||
|
||||
if (i>15) {
|
||||
msg+="\nAnd "+itos(failed_files.size()-i)+" more files.";
|
||||
break;
|
||||
}
|
||||
msg+=failed_files[i];
|
||||
}
|
||||
EditorNode::get_singleton()->show_warning(msg);
|
||||
} else {
|
||||
EditorNode::get_singleton()->show_warning("Package Installed Successfully!","Success!");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void EditorAssetInstaller::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method("_item_edited",&EditorAssetInstaller::_item_edited);
|
||||
|
||||
}
|
||||
|
||||
EditorAssetInstaller::EditorAssetInstaller() {
|
||||
|
||||
VBoxContainer *vb = memnew( VBoxContainer );
|
||||
add_child(vb);
|
||||
set_child_rect(vb);
|
||||
|
||||
tree = memnew( Tree );
|
||||
vb->add_margin_child("Package Contents:",tree,true);
|
||||
tree->connect("item_edited",this,"_item_edited");
|
||||
|
||||
error = memnew( AcceptDialog) ;
|
||||
add_child(error);
|
||||
get_ok()->set_text("Install");
|
||||
set_title("Package Installer");
|
||||
|
||||
updating=false;
|
||||
|
||||
set_hide_on_ok(true);
|
||||
}
|
||||
|
28
tools/editor/editor_asset_installer.h
Normal file
28
tools/editor/editor_asset_installer.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
#ifndef EDITORASSETINSTALLER_H
|
||||
#define EDITORASSETINSTALLER_H
|
||||
|
||||
|
||||
#include "scene/gui/dialogs.h"
|
||||
#include "scene/gui/tree.h"
|
||||
class EditorAssetInstaller : public ConfirmationDialog {
|
||||
|
||||
OBJ_TYPE( EditorAssetInstaller, ConfirmationDialog );
|
||||
|
||||
Tree *tree;
|
||||
String package_path;
|
||||
AcceptDialog *error;
|
||||
Map<String,TreeItem*> status_map;
|
||||
bool updating;
|
||||
void _update_subitems(TreeItem* p_item,bool p_check,bool p_first=false);
|
||||
void _item_edited();
|
||||
virtual void ok_pressed();
|
||||
protected:
|
||||
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void open(const String& p_path,int p_depth=0);
|
||||
EditorAssetInstaller();
|
||||
};
|
||||
|
||||
#endif // EDITORASSETINSTALLER_H
|
21
tools/editor/editor_initialize_ssl.cpp
Normal file
21
tools/editor/editor_initialize_ssl.cpp
Normal file
|
@ -0,0 +1,21 @@
|
|||
#include "editor_initialize_ssl.h"
|
||||
#include "certs_compressed.h"
|
||||
#include "io/stream_peer_ssl.h"
|
||||
#include "io/compression.h"
|
||||
|
||||
void editor_initialize_certificates() {
|
||||
|
||||
|
||||
ByteArray data;
|
||||
data.resize(_certs_uncompressed_size);
|
||||
{
|
||||
ByteArray::Write w = data.write();
|
||||
Compression::decompress(w.ptr(),_certs_uncompressed_size,_certs_compressed,_certs_compressed_size,Compression::MODE_DEFLATE);
|
||||
}
|
||||
|
||||
StreamPeerSSL::load_certs_from_memory(data);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
6
tools/editor/editor_initialize_ssl.h
Normal file
6
tools/editor/editor_initialize_ssl.h
Normal file
|
@ -0,0 +1,6 @@
|
|||
#ifndef EDITOR_INITIALIZE_SSL_H
|
||||
#define EDITOR_INITIALIZE_SSL_H
|
||||
|
||||
void editor_initialize_certificates();
|
||||
|
||||
#endif // EDITOR_INITIALIZE_SSL_H
|
|
@ -107,7 +107,7 @@
|
|||
#include "tools/editor/io_plugins/editor_export_scene.h"
|
||||
|
||||
#include "plugins/editor_preview_plugins.h"
|
||||
|
||||
#include "editor_initialize_ssl.h"
|
||||
#include "script_editor_debugger.h"
|
||||
|
||||
EditorNode *EditorNode::singleton=NULL;
|
||||
|
@ -4145,9 +4145,10 @@ Error EditorNode::export_platform(const String& p_platform, const String& p_path
|
|||
return OK;
|
||||
}
|
||||
|
||||
void EditorNode::show_warning(const String& p_text) {
|
||||
void EditorNode::show_warning(const String& p_text, const String &p_title) {
|
||||
|
||||
warning->set_text(p_text);
|
||||
warning->set_title(p_title);
|
||||
warning->popup_centered_minsize();
|
||||
}
|
||||
|
||||
|
@ -4950,6 +4951,7 @@ EditorNode::EditorNode() {
|
|||
|
||||
EditorHelp::generate_doc(); //before any editor classes are crated
|
||||
SceneState::set_disable_placeholders(true);
|
||||
editor_initialize_certificates(); //for asset sharing
|
||||
|
||||
|
||||
InputDefault *id = Input::get_singleton()->cast_to<InputDefault>();
|
||||
|
|
|
@ -655,7 +655,7 @@ public:
|
|||
Ref<Theme> get_editor_theme() const { return theme; }
|
||||
|
||||
|
||||
void show_warning(const String& p_text);
|
||||
void show_warning(const String& p_text,const String& p_title="Warning!");
|
||||
|
||||
|
||||
Error export_platform(const String& p_platform, const String& p_path, bool p_debug,const String& p_password,bool p_quit_after=false);
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 476 B After Width: | Height: | Size: 288 B |
Binary file not shown.
Before Width: | Height: | Size: 896 B After Width: | Height: | Size: 289 B |
|
@ -140,6 +140,9 @@ void BackgroundProgress::end_task(const String& p_task){
|
|||
|
||||
////////////////////////////////////////////////
|
||||
|
||||
|
||||
ProgressDialog *ProgressDialog::singleton=NULL;
|
||||
|
||||
void ProgressDialog::_notification(int p_what) {
|
||||
|
||||
switch(p_what) {
|
||||
|
@ -237,4 +240,5 @@ ProgressDialog::ProgressDialog() {
|
|||
main->set_area_as_parent_rect();
|
||||
set_exclusive(true);
|
||||
last_progress_tick=0;
|
||||
singleton=this;
|
||||
}
|
||||
|
|
|
@ -86,12 +86,14 @@ class ProgressDialog : public Popup {
|
|||
VBoxContainer *main;
|
||||
uint64_t last_progress_tick;
|
||||
|
||||
static ProgressDialog *singleton;
|
||||
void _popup();
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
public:
|
||||
|
||||
static ProgressDialog *get_singleton() { return singleton; }
|
||||
void add_task(const String& p_task,const String& p_label, int p_steps);
|
||||
void task_step(const String& p_task, const String& p_state, int p_step=-1, bool p_force_redraw=true);
|
||||
void end_task(const String& p_task);
|
||||
|
|
|
@ -1396,6 +1396,11 @@ void ProjectSettings::_clear_search_box() {
|
|||
globals_editor->get_property_editor()->update_tree();
|
||||
}
|
||||
|
||||
void ProjectSettings::set_plugins_page() {
|
||||
|
||||
tab_container->set_current_tab( plugin_settings->get_index() );
|
||||
}
|
||||
|
||||
void ProjectSettings::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("_item_selected"),&ProjectSettings::_item_selected);
|
||||
|
@ -1452,7 +1457,7 @@ ProjectSettings::ProjectSettings(EditorData *p_data) {
|
|||
data=p_data;
|
||||
|
||||
|
||||
TabContainer *tab_container = memnew( TabContainer );
|
||||
tab_container = memnew( TabContainer );
|
||||
add_child(tab_container);
|
||||
set_child_rect(tab_container);
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include "optimized_save_dialog.h"
|
||||
#include "undo_redo.h"
|
||||
#include "editor_data.h"
|
||||
|
||||
#include "scene/gui/tab_container.h"
|
||||
#include "editor_plugin_settings.h"
|
||||
|
||||
//#include "project_export_settings.h"
|
||||
|
@ -42,6 +42,9 @@
|
|||
class ProjectSettings : public AcceptDialog {
|
||||
OBJ_TYPE( ProjectSettings, AcceptDialog );
|
||||
|
||||
|
||||
TabContainer *tab_container;
|
||||
|
||||
Timer *timer;
|
||||
InputEvent::Type add_type;
|
||||
String add_at;
|
||||
|
@ -164,6 +167,7 @@ public:
|
|||
void add_translation(const String& p_translation);
|
||||
static ProjectSettings *get_singleton() { return singleton; }
|
||||
void popup_project_settings();
|
||||
void set_plugins_page();
|
||||
|
||||
void queue_save();
|
||||
|
||||
|
|
Loading…
Reference in a new issue