Browse Source

Update asset library editor plugin - new functionality and fixes

Bojidar Marinov 9 years ago
parent
commit
e4a24812cd

+ 1 - 0
scene/main/http_request.cpp

@@ -499,6 +499,7 @@ HTTPRequest::HTTPRequest()
 	use_ssl=false;
 	response_code=0;
 	request_sent=false;
+	requesting=false;
 	client.instance();
 	use_threads=false;
 	body_size_limit=-1;

+ 373 - 205
tools/editor/addon_editor_plugin.cpp → tools/editor/asset_library_editor_plugin.cpp

@@ -1,4 +1,32 @@
-#include "addon_editor_plugin.h"
+/*************************************************************************/
+/*  asset_library_editor_plugin.cpp                                      */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                    http://www.godotengine.org                         */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur.                 */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+#include "asset_library_editor_plugin.h"
 #include "editor_node.h"
 #include "editor_settings.h"
 
@@ -16,10 +44,10 @@ void EditorAssetLibraryItem::configure(const String& p_title,int p_asset_id,cons
 	price->set_text(p_cost);
 
 	for(int i=0;i<5;i++) {
-		if (i>2)
-			stars[i]->set_texture(get_icon("RatingNoStar","EditorIcons"));
-		else
+		if (i<p_rating)
 			stars[i]->set_texture(get_icon("RatingStar","EditorIcons"));
+		else
+			stars[i]->set_texture(get_icon("RatingNoStar","EditorIcons"));
 	}
 
 
@@ -149,6 +177,7 @@ void EditorAddonLibraryItemDescription::set_image(int p_type,int p_index,const R
 			for(int i=0;i<preview_images.size();i++) {
 				if (preview_images[i].id==p_index) {
 					preview_images[i].button->set_icon(p_image);
+					break;
 				}
 			}
 			//item->call("set_image",p_type,p_index,p_image);
@@ -156,8 +185,12 @@ void EditorAddonLibraryItemDescription::set_image(int p_type,int p_index,const R
 		case EditorAddonLibrary::IMAGE_QUEUE_SCREENSHOT: {
 
 			for(int i=0;i<preview_images.size();i++) {
-				if (preview_images[i].id==p_index && preview_images[i].button->is_pressed()) {
-					preview->set_texture(p_image);
+				if (preview_images[i].id==p_index) {
+					preview_images[i].image = p_image;
+					if(preview_images[i].button->is_pressed()) {
+						_preview_click(p_index);
+					}
+					break;
 				}
 			}
 			//item->call("set_image",p_type,p_index,p_image);
@@ -168,29 +201,46 @@ 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);
+	ObjectTypeDB::bind_method(_MD("_preview_click"),&EditorAddonLibraryItemDescription::_preview_click);
 
 }
 
 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) {
+void EditorAddonLibraryItemDescription::_preview_click(int p_id) {
+	for(int i=0;i<preview_images.size();i++) {
+		if(preview_images[i].id==p_id) {
+			preview_images[i].button->set_pressed(true);
+			if(!preview_images[i].is_video) {
+				if(preview_images[i].image.is_valid()) {
+					preview->set_texture(preview_images[i].image);
+				}
+			} else {
+				_link_click(preview_images[i].video_link);
+			}
+		} else {
+			preview_images[i].button->set_pressed(false);
+		}
+	}
+}
+
+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,int p_version,const String& p_version_string,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->clear();
-	description->add_text("Version: "+p_version+"\n");
+	description->add_text("Version: "+p_version_string+"\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);
+	description->append_bbcode(p_description); 
 	set_title(p_title);
 }
 
@@ -199,13 +249,19 @@ void EditorAddonLibraryItemDescription::add_preview(int p_id, bool p_video,const
 	Preview preview;
 	preview.id=p_id;
 	preview.video_link=p_url;
+	preview.is_video=p_video;
 	preview.button = memnew( Button );
 	preview.button->set_flat(true);
 	preview.button->set_icon(get_icon("ThumbnailWait","EditorIcons"));
 	preview.button->set_toggle_mode(true);
+	preview.button->connect("pressed", this, "_preview_click", varray(p_id));
 	preview_hb->add_child(preview.button);
-	if (preview_images.size()==0)
-		preview.button->set_pressed(true);
+	if(!p_video) {
+		preview.image=get_icon("ThumbnailWait","EditorIcons");
+	}
+	if(preview_images.size()==0 && !p_video) {
+		_preview_click(p_id);
+	}
 	preview_images.push_back(preview);
 }
 
@@ -257,7 +313,7 @@ EditorAddonLibraryItemDescription::EditorAddonLibraryItemDescription() {
 
 	previews->add_child(preview_hb);
 	get_ok()->set_text("Install");
-	get_cancel()->set_text(TTR("Close"));
+	get_cancel()->set_text("Close");
 
 
 
@@ -337,14 +393,9 @@ void EditorAddonLibraryItemDownload::configure(const String& p_title,int p_asset
 		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"));
-
-
+	dismiss->set_normal_texture( get_icon("Close","EditorIcons"));
+	_make_request();
 }
 
 
@@ -392,11 +443,23 @@ void EditorAddonLibraryItemDownload::_install() {
 	asset_installer->open(file,1);
 }
 
+void EditorAddonLibraryItemDownload::_make_request() {
+	download->cancel_request();
+	download->set_download_file(EditorSettings::get_singleton()->get_settings_path().plus_file("tmp").plus_file("tmp_asset_"+itos(asset_id))+".zip");
+	Error err = download->request(host);
+	if(err!=OK) {
+		status->set_text("Error making request");
+	} else {
+		set_process(true);
+	}
+}
+
 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);
+	ObjectTypeDB::bind_method("_make_request",&EditorAddonLibraryItemDownload::_make_request);
 
 }
 
@@ -442,6 +505,11 @@ EditorAddonLibraryItemDownload::EditorAddonLibraryItemDownload() {
 	install->set_disabled(true);
 	install->connect("pressed",this,"_install");
 
+	retry = memnew( Button );
+	retry->set_text("Retry");
+	retry->connect("pressed",this,"_make_request");
+
+	hb2->add_child(retry);
 	hb2->add_child(install);
 	set_custom_minimum_size(Size2(250,0));
 
@@ -472,7 +540,7 @@ void EditorAddonLibrary::_notification(int p_what) {
 		error_hb->add_child(tf);
 		error_label->raise();
 
-		_api_request("api/configure");
+		_repository_changed(0);
 	}
 
 	if (p_what==NOTIFICATION_PROCESS) {
@@ -572,7 +640,7 @@ void EditorAddonLibrary::_select_category(int p_id){
 }
 void EditorAddonLibrary::_select_asset(int p_id){
 
-	_api_request("api/asset","?id="+itos(p_id));
+	_api_request("asset/"+itos(p_id), REQUESTING_ASSET);
 
 	/*
 	if (description) {
@@ -585,33 +653,102 @@ void EditorAddonLibrary::_select_asset(int p_id){
 	description->popup_centered_minsize();*/
 }
 
+void EditorAddonLibrary::_image_update(bool use_cache, bool final, const ByteArray& p_data, int p_queue_id) {
+	Object *obj = ObjectDB::get_instance(image_queue[p_queue_id].target);
+
+	if (obj) {
+		bool image_set = false;
+		ByteArray image_data = p_data;
+		
+		if(use_cache) {
+			String cache_filename_base = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp").plus_file("assetimage_"+image_queue[p_queue_id].image_url.md5_text());
+			
+			FileAccess* file = FileAccess::open(cache_filename_base+".data", FileAccess::READ);
+			
+			if(file) {
+				ByteArray cached_data;
+				int len=file->get_32();
+				cached_data.resize(len);
+				
+				ByteArray::Write w=cached_data.write();
+				file->get_buffer(w.ptr(), len);
+				
+				image_data = cached_data;
+				file->close();
+			}
+		}
+		
+		int len=image_data.size();
+		ByteArray::Read r=image_data.read();
+		Image image(r.ptr(),len);
+		if (!image.empty()) {
+			float max_height = 10000;
+			switch(image_queue[p_queue_id].image_type) {
+				case IMAGE_QUEUE_ICON: max_height=80; break;
+				case IMAGE_QUEUE_THUMBNAIL: max_height=80; break;
+				case IMAGE_QUEUE_SCREENSHOT: max_height=345; break;
+			}
+			float scale_ratio = max_height / image.get_height();
+			if(scale_ratio < 1) {
+				image.resize(image.get_width() * scale_ratio, image.get_height() * scale_ratio, Image::INTERPOLATE_CUBIC);
+			}
+
+			Ref<ImageTexture> tex;
+			tex.instance();
+			tex->create_from_image(image);
 
+			obj->call("set_image",image_queue[p_queue_id].image_type,image_queue[p_queue_id].image_index,tex);
+			image_set = true;
+		}
+		
+		if(!image_set && final) {
+			obj->call("set_image",image_queue[p_queue_id].image_type,image_queue[p_queue_id].image_index,get_icon("ErrorSign","EditorIcons"));
+		}
+	}
+}
 
 void EditorAddonLibrary::_image_request_completed(int p_status, int p_code, const StringArray& headers, const ByteArray& p_data,int p_queue_id) {
 
 	ERR_FAIL_COND( !image_queue.has(p_queue_id) );
 
 	if (p_status==HTTPRequest::RESULT_SUCCESS) {
-
-
+		
 		print_line("GOT IMAGE YAY!");
-		Object *obj = ObjectDB::get_instance(image_queue[p_queue_id].target);
-
-		if (obj) {
-			int len=p_data.size();
-			ByteArray::Read r=p_data.read();
-
-			Image image(r.ptr(),len);
-			if (!image.empty()) {
-				Ref<ImageTexture> tex;
-				tex.instance();
-				tex->create_from_image(image);
-
-				obj->call("set_image",image_queue[p_queue_id].image_type,image_queue[p_queue_id].image_index,tex);
+		
+		if(p_code != HTTPClient::RESPONSE_NOT_MODIFIED) {
+			for(int i=0;i<headers.size();i++) {
+				if (headers[i].findn("ETag:")==0) { // Save etag
+					String cache_filename_base = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp").plus_file("assetimage_"+image_queue[p_queue_id].image_url.md5_text());
+					String new_etag = headers[i].substr(headers[i].find(":")+1,headers[i].length()).strip_edges();
+					FileAccess* file;
+					
+					file = FileAccess::open(cache_filename_base+".etag", FileAccess::WRITE);
+					if(file) {
+						file->store_line(new_etag);
+						file->close();
+					}
+					
+					int len=p_data.size();
+					ByteArray::Read r=p_data.read();
+					file = FileAccess::open(cache_filename_base+".data", FileAccess::WRITE);
+					if(file) {
+						file->store_32(len);
+						file->store_buffer(r.ptr(),len);
+						file->close();
+					}
+					
+					break;
+				}
 			}
 		}
+		_image_update(p_code == HTTPClient::RESPONSE_NOT_MODIFIED, true, p_data, p_queue_id);
+		
 	} else {
 		WARN_PRINTS("Error getting PNG file for asset id "+itos(image_queue[p_queue_id].asset_id));
+		Object *obj = ObjectDB::get_instance(image_queue[p_queue_id].target);
+		if (obj) {
+			obj->call("set_image",image_queue[p_queue_id].image_type,image_queue[p_queue_id].image_index,get_icon("ErrorSign","EditorIcons"));
+		}
 	}
 
 	image_queue[p_queue_id].request->queue_delete();;
@@ -629,16 +766,20 @@ void EditorAddonLibrary::_update_image_queue() {
 	List<int> to_delete;
 	for (Map<int,ImageQueue>::Element *E=image_queue.front();E;E=E->next()) {
 		if (!E->get().active && current_images<max_images) {
-
-			String api;
-			switch(E->get().image_type) {
-				case IMAGE_QUEUE_ICON: api="api/icon/icon.png"; break;
-				case IMAGE_QUEUE_SCREENSHOT: api="api/screenshot/screenshot.png"; break;
-				case IMAGE_QUEUE_THUMBNAIL: api="api/thumbnail/thumbnail.png"; break;
+			
+			String cache_filename_base = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp").plus_file("assetimage_"+E->get().image_url.md5_text());
+			Vector<String> headers;
+			
+			if(FileAccess::exists(cache_filename_base+".etag") && FileAccess::exists(cache_filename_base+".data")) {
+				FileAccess* file = FileAccess::open(cache_filename_base+".etag", FileAccess::READ);
+				if (file) {
+					headers.push_back("If-None-Match: " + file->get_line());
+					file->close();
+				}
 			}
 
 			print_line("REQUEST ICON FOR: "+itos(E->get().asset_id));
-			Error err = E->get().request->request(host+"/"+api+"?asset_id="+itos(E->get().asset_id)+"&index="+itos(E->get().image_index));
+			Error err = E->get().request->request(E->get().image_url, headers);
 			if (err!=OK) {
 				to_delete.push_back(E->key());
 			} else {
@@ -657,11 +798,11 @@ void EditorAddonLibrary::_update_image_queue() {
 	}
 }
 
-void EditorAddonLibrary::_request_image(ObjectID p_for,int p_asset_id,ImageType p_type,int p_image_index) {
+void EditorAddonLibrary::_request_image(ObjectID p_for,String p_image_url,ImageType p_type,int p_image_index) {
 
 
 	ImageQueue iq;
-	iq.asset_id=p_asset_id;
+	iq.image_url=p_image_url;
 	iq.image_index=p_image_index;
 	iq.image_type=p_type;
 	iq.request = memnew( HTTPRequest );
@@ -676,11 +817,17 @@ void EditorAddonLibrary::_request_image(ObjectID p_for,int p_asset_id,ImageType
 
 	add_child(iq.request);
 
+	_image_update(true, false, ByteArray(), iq.queue_id);
 	_update_image_queue();
 
 
 }
 
+void EditorAddonLibrary::_repository_changed(int p_repository_id) {
+	host=repository->get_item_metadata(p_repository_id);
+	print_line(".." + host);
+	_api_request("configure", REQUESTING_CONFIG);
+}
 
 void EditorAddonLibrary::_search(int p_page) {
 
@@ -692,7 +839,12 @@ void EditorAddonLibrary::_search(int p_page) {
 
 		args+="&category="+itos(categories->get_item_metadata(categories->get_selected()));
 	}
+	
+	if (reverse->is_pressed()) {
 
+		args+="&reverse=true";
+	}
+	
 	if (filter->get_text()!=String()) {
 		args+="&filter="+filter->get_text().http_escape();
 	}
@@ -701,10 +853,10 @@ void EditorAddonLibrary::_search(int p_page) {
 		args+="&page="+itos(p_page);
 	}
 
-	_api_request("api/search",args);
+	_api_request("asset",REQUESTING_SEARCH,args);
 }
 
-HBoxContainer* EditorAddonLibrary::_make_pages(int p_page,int p_max_page,int p_page_len,int p_total_items,int p_current_items) {
+HBoxContainer* EditorAddonLibrary::_make_pages(int p_page,int p_page_count,int p_page_len,int p_total_items,int p_current_items) {
 
 	HBoxContainer * hbc = memnew( HBoxContainer );
 
@@ -713,20 +865,22 @@ HBoxContainer* EditorAddonLibrary::_make_pages(int p_page,int p_max_page,int p_p
 	if (from<0)
 		from=0;
 	int to = from+10;
-	if (to>p_max_page)
-		to=p_max_page;
+	if (to>p_page_count)
+		to=p_page_count;
 
 	Color gray = Color(0.65,0.65,0.65);
 
 	hbc->add_spacer();
 	hbc->add_constant_override("separation",10);
 
-	LinkButton *first = memnew( LinkButton );
-	first->set_text("first");
-	first->add_color_override("font_color", gray );
-	first->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
-	first->connect("pressed",this,"_search",varray(0));
-	hbc->add_child(first);
+	if(p_page != 0) {
+		LinkButton *first = memnew( LinkButton );
+		first->set_text("first");
+		first->add_color_override("font_color", gray );
+		first->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
+		first->connect("pressed",this,"_search",varray(0));
+		hbc->add_child(first);
+	}
 
 	if (p_page>0) {
 		LinkButton *prev = memnew( LinkButton );
@@ -737,19 +891,19 @@ HBoxContainer* EditorAddonLibrary::_make_pages(int p_page,int p_max_page,int p_p
 		hbc->add_child(prev);
 	}
 
-	for(int i=from;i<=to;i++) {
+	for(int i=from;i<to;i++) {
 
 		if (i==p_page) {
 
 			Label *current = memnew(Label);
-			current->set_text(itos(i));
+			current->set_text(itos(i+1));
 			hbc->add_child(current);
 		} else {
 
 			LinkButton *current = memnew( LinkButton );
 			current->add_color_override("font_color", gray );
 			current->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
-			current->set_text(itos(i));
+			current->set_text(itos(i+1));
 			current->connect("pressed",this,"_search",varray(i));
 
 			hbc->add_child(current);
@@ -757,7 +911,7 @@ HBoxContainer* EditorAddonLibrary::_make_pages(int p_page,int p_max_page,int p_p
 		}
 	}
 
-	if (p_page<p_max_page) {
+	if (p_page<p_page_count-1) {
 		LinkButton *next = memnew( LinkButton );
 		next->set_text("next");
 		next->add_color_override("font_color", gray );
@@ -766,12 +920,15 @@ HBoxContainer* EditorAddonLibrary::_make_pages(int p_page,int p_max_page,int p_p
 
 		hbc->add_child(next);
 	}
-	LinkButton *last = memnew( LinkButton );
-	last->set_text("last");
-	last->add_color_override("font_color", gray );
-	last->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
-	hbc->add_child(last);
-	last->connect("pressed",this,"_search",varray(p_max_page));
+
+	if(p_page != p_page_count-1) {
+		LinkButton *last = memnew( LinkButton );
+		last->set_text("last");
+		last->add_color_override("font_color", gray );
+		last->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
+		hbc->add_child(last);
+		last->connect("pressed",this,"_search",varray(p_page_count-1));
+	}
 
 	Label *totals = memnew( Label );
 	totals->set_text("( "+itos(from*p_page_len)+" - "+itos(from*p_page_len+p_current_items-1)+" / "+itos(p_total_items)+" )");
@@ -783,14 +940,14 @@ HBoxContainer* EditorAddonLibrary::_make_pages(int p_page,int p_max_page,int p_p
 }
 
 
-void EditorAddonLibrary::_api_request(const String& p_request,const String& p_arguments) {
+void EditorAddonLibrary::_api_request(const String& p_request, RequestType p_request_type, const String& p_arguments) {
 
 	if (requesting!=REQUESTING_NONE) {
 		request->cancel_request();
 	}
+	requesting=p_request_type;
 
 	error_hb->hide();
-	current_request=p_request;
 	request->request(host+"/"+p_request+p_arguments);
 }
 
@@ -856,165 +1013,173 @@ void EditorAddonLibrary::_http_request_completed(int p_status, int p_code, const
 
 	print_line(Variant(d).get_construct_string());
 
-	if (current_request=="api/configure") {
-
-		categories->clear();
-		categories->add_item("All");
-		categories->set_item_metadata(0,0);
-		if (d.has("categories")) {
-			Array clist = d["categories"];
-			for(int i=0;i<clist.size();i++) {
-				Dictionary cat = clist[i];
-				if (!cat.has("name") || !cat.has("id"))
-					continue;
-				String name=cat["name"];
-				int id=cat["id"];
-				categories->add_item(name);
-				categories->set_item_metadata( categories->get_item_count() -1, id);
+	RequestType requested = requesting;
+	requesting=REQUESTING_NONE;
+
+	switch(requested) {
+		case REQUESTING_CONFIG: {
+
+			categories->clear();
+			categories->add_item("All");
+			categories->set_item_metadata(0,0);
+			if (d.has("categories")) {
+				Array clist = d["categories"];
+				for(int i=0;i<clist.size();i++) {
+					Dictionary cat = clist[i];
+					if (!cat.has("name") || !cat.has("id"))
+						continue;
+					String name=cat["name"];
+					int id=cat["id"];
+					categories->add_item(name);
+					categories->set_item_metadata( categories->get_item_count() -1, id);
+					category_map[cat["id"]] = name;
+				}
 			}
-		}
 
-		_search();
-	} else if (current_request=="api/search") {
-
-		if (asset_items) {
-			memdelete(asset_items);
-		}
-
-		if (asset_top_page) {
-			memdelete(asset_top_page);
-		}
-
-		if (asset_bottom_page) {
-			memdelete(asset_bottom_page);
-		}
-
-		int page=0;
-		int pages=1;
-		int page_len=10;
-		int total_items=1;
-		Array result;
-
-
-		if (d.has("page")) {
-			page=d["page"];
-		}
-		if (d.has("pages")) {
-			pages=d["pages"];
-		}
-		if (d.has("page_length")) {
-			page_len=d["page_length"];
-		}
-		if (d.has("total")) {
-			total_items=d["total"];
-		}
-		if (d.has("result")) {
-			result=d["result"];
-		}
-
-		asset_top_page = _make_pages(page,pages,page_len,total_items,result.size());
-		library_vb->add_child(asset_top_page);
+			_search();
+		} break;
+		case REQUESTING_SEARCH: {
+			if (asset_items) {
+				memdelete(asset_items);
+			}
 
-		asset_items = memnew( GridContainer );
-		asset_items->set_columns(2);
-		asset_items->add_constant_override("hseparation",10);
-		asset_items->add_constant_override("vseparation",10);
+			if (asset_top_page) {
+				memdelete(asset_top_page);
+			}
 
-		library_vb->add_child(asset_items);
+			if (asset_bottom_page) {
+				memdelete(asset_bottom_page);
+			}
 
-		asset_bottom_page = _make_pages(page,pages,page_len,total_items,result.size());
-		library_vb->add_child(asset_bottom_page);
+			int page=0;
+			int pages=1;
+			int page_len=10;
+			int total_items=1;
+			Array result;
 
-		for(int i=0;i<result.size();i++) {
 
-			Dictionary r = result[i];
+			if (d.has("page")) {
+				page=d["page"];
+			}
+			if (d.has("pages")) {
+				pages=d["pages"];
+			}
+			if (d.has("page_length")) {
+				page_len=d["page_length"];
+			}
+			if (d.has("total")) {
+				total_items=d["total"];
+			}
+			if (d.has("result")) {
+				result=d["result"];
+			}
 
-			ERR_CONTINUE(!r.has("title"));
-			ERR_CONTINUE(!r.has("asset_id"));
-			ERR_CONTINUE(!r.has("author"));
-			ERR_CONTINUE(!r.has("author_id"));
-			ERR_CONTINUE(!r.has("category"));
-			ERR_CONTINUE(!r.has("category_id"));
-			ERR_CONTINUE(!r.has("rating"));
-			ERR_CONTINUE(!r.has("cost"));
+			asset_top_page = _make_pages(page,pages,page_len,total_items,result.size());
+			library_vb->add_child(asset_top_page);
 
+			asset_items = memnew( GridContainer );
+			asset_items->set_columns(2);
+			asset_items->add_constant_override("hseparation",10);
+			asset_items->add_constant_override("vseparation",10);
 
-			EditorAssetLibraryItem *item = memnew( EditorAssetLibraryItem );
-			asset_items->add_child(item);
-			item->configure(r["title"],r["asset_id"],r["category"],r["category_id"],r["author"],r["author_id"],r["rating"],r["cost"]);
-			item->connect("asset_selected",this,"_select_asset");
-			item->connect("author_selected",this,"_select_author");
-			item->connect("category_selected",this,"_category_selected");
+			library_vb->add_child(asset_items);
 
-			_request_image(item->get_instance_ID(),r["asset_id"],IMAGE_QUEUE_ICON,0);
-		}
-	} else if (current_request=="api/asset") {
+			asset_bottom_page = _make_pages(page,pages,page_len,total_items,result.size());
+			library_vb->add_child(asset_bottom_page);
 
-		ERR_FAIL_COND(!d.has("info"));
+			for(int i=0;i<result.size();i++) {
 
-		Dictionary r = d["info"];
+				Dictionary r = result[i];
 
-		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_CONTINUE(!r.has("title"));
+				ERR_CONTINUE(!r.has("asset_id"));
+				ERR_CONTINUE(!r.has("author"));
+				ERR_CONTINUE(!r.has("author_id"));
+				ERR_CONTINUE(!r.has("category_id"));
+				ERR_FAIL_COND(!category_map.has(r["category_id"]));
+				ERR_CONTINUE(!r.has("rating"));
+				ERR_CONTINUE(!r.has("cost"));
 
-		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"));
 
+				EditorAssetLibraryItem *item = memnew( EditorAssetLibraryItem );
+				asset_items->add_child(item);
+				item->configure(r["title"],r["asset_id"],category_map[r["category_id"]],r["category_id"],r["author"],r["author_id"],r["rating"],r["cost"]);
+				item->connect("asset_selected",this,"_select_asset");
+				item->connect("author_selected",this,"_select_author");
+				item->connect("category_selected",this,"_select_category");
 
-		if (description) {
-			memdelete(description);
-		}
+				if(r.has("icon_url") && r["icon_url"] != "") {
+					_request_image(item->get_instance_ID(),r["icon_url"],IMAGE_QUEUE_ICON,0);
+				}
+			}
+		} break;
+		case REQUESTING_ASSET: {
+			Dictionary r = d;
+
+			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("version_string"));
+			ERR_FAIL_COND(!r.has("category_id"));
+			ERR_FAIL_COND(!category_map.has(r["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);
+			}
 
-		description = memnew( EditorAddonLibraryItemDescription );
-		add_child(description);
-		description->popup_centered_minsize();
-		description->connect("confirmed",this,"_install_asset");
+			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["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");*/
+			description->configure(r["title"],r["asset_id"],category_map[r["category_id"]],r["category_id"],r["author"],r["author_id"],r["rating"],r["cost"],r["version"],r["version_string"],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");*/
 
-		_request_image(description->get_instance_ID(),r["asset_id"],IMAGE_QUEUE_ICON,0);
+			if(r.has("icon_url") && r["icon_url"] != "") {
+				_request_image(description->get_instance_ID(),r["icon_url"],IMAGE_QUEUE_ICON,0);
+			}
 
-		if (d.has("previews")) {
-			Array previews = d["previews"];
+			if (d.has("previews")) {
+				Array previews = d["previews"];
 
-			for(int i=0;i<previews.size();i++) {
+				for(int i=0;i<previews.size();i++) {
 
 
-				Dictionary p=previews[i];
+					Dictionary p=previews[i];
 
-				ERR_CONTINUE(!p.has("id"));
+					ERR_CONTINUE(!p.has("type"));
+					ERR_CONTINUE(!p.has("link"));
 
-				bool is_video=p.has("type") && String(p["type"])=="video";
-				String video_url;
-				if (is_video && p.has("link")) {
-					video_url="link";
-				}
+					bool is_video=p.has("type") && String(p["type"])=="video";
+					String video_url;
+					if (is_video && p.has("link")) {
+						video_url=p["link"];
+					}
 
-				int id=p["id"];
+					description->add_preview(i,is_video,video_url);
 
-				description->add_preview(id,is_video,video_url);
+					if(p.has("thumbnail")) {
+						_request_image(description->get_instance_ID(),p["thumbnail"],IMAGE_QUEUE_THUMBNAIL,i);
+					}
+					if(is_video) {
+						//_request_image(description->get_instance_ID(),p["link"],IMAGE_QUEUE_SCREENSHOT,i);
+					} else {
+						_request_image(description->get_instance_ID(),p["link"],IMAGE_QUEUE_SCREENSHOT,i);
+					}
 
-				_request_image(description->get_instance_ID(),r["asset_id"],IMAGE_QUEUE_THUMBNAIL,id);
-				if (i==0) {
-					_request_image(description->get_instance_ID(),r["asset_id"],IMAGE_QUEUE_SCREENSHOT,id);
 				}
-
 			}
-		}
+		} break;
+		default: break;
 	}
 
 }
@@ -1059,6 +1224,7 @@ void EditorAddonLibrary::_bind_methods() {
 	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);
+	ObjectTypeDB::bind_method("_repository_changed",&EditorAddonLibrary::_repository_changed);
 
 }
 
@@ -1090,19 +1256,19 @@ EditorAddonLibrary::EditorAddonLibrary() {
 	search_hb->add_child(filter);
 	filter->set_h_size_flags(SIZE_EXPAND_FILL);
 	filter->connect("text_entered",this,"_search");
-	search = memnew( Button(TTR("Search")));
+	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(TTR("Import"));
+	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(TTR("Plugins"));
+	plugins->set_text("Plugins");
 	search_hb->add_child(plugins);
 	plugins->connect("pressed",this,"_manage_plugins");
 
@@ -1142,7 +1308,12 @@ EditorAddonLibrary::EditorAddonLibrary() {
 	search_hb2->add_child( memnew( Label(TTR("Site:")+" ")));
 	repository = memnew( OptionButton );
 
+	repository->add_item("Localhost"); // TODO: Maybe remove?
+	repository->set_item_metadata(0, "http://127.0.0.1/addonlib/api");
 	repository->add_item("Godot");
+	repository->set_item_metadata(1, "http://godotengine.org/addonlib/api");
+	repository->connect("item_selected",this,"_repository_changed");
+
 	search_hb2->add_child(repository);
 	repository->set_h_size_flags(SIZE_EXPAND_FILL);
 
@@ -1199,7 +1370,6 @@ EditorAddonLibrary::EditorAddonLibrary() {
 	add_child(request);
 	request->connect("request_completed",this,"_http_request_completed");
 
-
 	last_queue_id=0;
 
 	library_vb->add_constant_override("separation",20);
@@ -1218,8 +1388,6 @@ EditorAddonLibrary::EditorAddonLibrary() {
 
 	description = NULL;
 
-	//host="http://localhost:8000";
-	host="http://godotengine.org/addonlib";
 	set_process(true);
 
 	downloads_scroll = memnew( ScrollContainer );
@@ -1245,7 +1413,7 @@ EditorAddonLibrary::EditorAddonLibrary() {
 ///////
 
 
-void AddonEditorPlugin::make_visible(bool p_visible) {
+void AssetLibraryEditorPlugin::make_visible(bool p_visible) {
 
 	if (p_visible) {
 
@@ -1257,7 +1425,7 @@ void AddonEditorPlugin::make_visible(bool p_visible) {
 
 }
 
-AddonEditorPlugin::AddonEditorPlugin(EditorNode *p_node) {
+AssetLibraryEditorPlugin::AssetLibraryEditorPlugin(EditorNode *p_node) {
 
 	editor=p_node;
 	addon_library = memnew( EditorAddonLibrary );
@@ -1268,6 +1436,6 @@ AddonEditorPlugin::AddonEditorPlugin(EditorNode *p_node) {
 
 }
 
-AddonEditorPlugin::~AddonEditorPlugin() {
+AssetLibraryEditorPlugin::~AssetLibraryEditorPlugin() {
 
 }

+ 50 - 14
tools/editor/addon_editor_plugin.h → tools/editor/asset_library_editor_plugin.h

@@ -1,5 +1,33 @@
-#ifndef ADDON_EDITOR_PLUGIN_H
-#define ADDON_EDITOR_PLUGIN_H
+/*************************************************************************/
+/*  asset_library_editor_plugin.h                                        */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                    http://www.godotengine.org                         */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur.                 */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+#ifndef ASSET_LIBRARY_EDITOR_PLUGIN_H
+#define ASSET_LIBRARY_EDITOR_PLUGIN_H
 
 
 #include "editor_plugin.h"
@@ -69,8 +97,10 @@ class EditorAddonLibraryItemDescription : public ConfirmationDialog {
 
 	struct Preview {
 		int id;
+		bool is_video;
 		String video_link;
 		Button *button;
+		Ref<Texture> image;
 	};
 
 	Vector<Preview> preview_images;
@@ -84,12 +114,13 @@ class EditorAddonLibraryItemDescription : public ConfirmationDialog {
 	Ref<Texture> icon;
 
 	void _link_click(const String& p_url);
+	void _preview_click(int p_index);
 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_version,const String& p_description,const String& p_download_url,const String& p_browse_url);
+	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,int p_version,const String& p_version_string,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; }
@@ -109,6 +140,7 @@ class EditorAddonLibraryItemDownload : public PanelContainer {
 	Label* title;
 	ProgressBar *progress;
 	Button *install;
+	Button *retry;
 	TextureButton *dismiss;
 
 	AcceptDialog *download_error;
@@ -124,6 +156,7 @@ class EditorAddonLibraryItemDownload : public PanelContainer {
 
 	void _close();
 	void _install();
+	void _make_request();
 	void _http_download_completed(int p_status, int p_code, const StringArray& headers, const ByteArray& p_data);
 
 protected:
@@ -202,6 +235,7 @@ class EditorAddonLibrary : public PanelContainer {
 		int asset_id;
 		ImageType image_type;
 		int image_index;
+		String image_url;
 		HTTPRequest *request;
 		ObjectID target;
 	};
@@ -209,27 +243,27 @@ class EditorAddonLibrary : public PanelContainer {
 	int last_queue_id;
 	Map<int,ImageQueue> image_queue;
 
-
+	void _image_update(bool use_cache, bool final, const ByteArray& p_data, int p_queue_id);
 	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 _request_image(ObjectID p_for,String p_image_url,ImageType p_type,int p_image_index);
 	void _update_image_queue();
 
-	HBoxContainer* _make_pages(int p_page, int p_max_page, int p_page_len, int p_total_items, int p_current_items);
+	HBoxContainer* _make_pages(int p_page, int p_page_count, int p_page_len, int p_total_items, int p_current_items);
 
 	//
 	EditorAddonLibraryItemDescription *description;
-
-	String current_request;
 	//
 
 	enum RequestType {
 		REQUESTING_NONE,
 		REQUESTING_CONFIG,
+		REQUESTING_SEARCH,
+		REQUESTING_ASSET,
 	};
 
 
 	RequestType requesting;
+	Dictionary category_map;
 
 
 	ScrollContainer *downloads_scroll;
@@ -246,10 +280,12 @@ class EditorAddonLibrary : public PanelContainer {
 	void _manage_plugins();
 
 	void _search(int p_page=0);
-	void _api_request(const String& p_request, const String &p_arguments="");
+	void _api_request(const String& p_request, RequestType p_request_type, 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);
 
+	void _repository_changed(int p_repository_id);
+
 friend class EditorAddonLibraryItemDescription;
 friend class EditorAssetLibraryItem;
 protected:
@@ -260,9 +296,9 @@ public:
 	EditorAddonLibrary();
 };
 
-class AddonEditorPlugin : public EditorPlugin {
+class AssetLibraryEditorPlugin : public EditorPlugin {
 
-	OBJ_TYPE( AddonEditorPlugin, EditorPlugin );
+	OBJ_TYPE( AssetLibraryEditorPlugin, EditorPlugin );
 
 	EditorAddonLibrary *addon_library;
 	EditorNode *editor;
@@ -278,8 +314,8 @@ public:
 	//virtual Dictionary get_state() const;
 	//virtual void set_state(const Dictionary& p_state);
 
-	AddonEditorPlugin(EditorNode *p_node);
-	~AddonEditorPlugin();
+	AssetLibraryEditorPlugin(EditorNode *p_node);
+	~AssetLibraryEditorPlugin();
 
 };
 

+ 2 - 2
tools/editor/editor_node.cpp

@@ -61,7 +61,7 @@
 #include "plugins/sprite_frames_editor_plugin.h"
 #include "plugins/texture_region_editor_plugin.h"
 #include "plugins/canvas_item_editor_plugin.h"
-#include "addon_editor_plugin.h"
+#include "asset_library_editor_plugin.h"
 #include "plugins/spatial_editor_plugin.h"
 #include "plugins/sample_editor_plugin.h"
 #include "plugins/texture_editor_plugin.h"
@@ -6378,7 +6378,7 @@ EditorNode::EditorNode() {
 	add_editor_plugin( memnew( CanvasItemEditorPlugin(this) ) );
 	add_editor_plugin( memnew( SpatialEditorPlugin(this) ) );
 	add_editor_plugin( memnew( ScriptEditorPlugin(this) ) );
-	//add_editor_plugin( memnew( AddonEditorPlugin(this) ) );
+	add_editor_plugin( memnew( AssetLibraryEditorPlugin(this) ) );
 
 	//more visually meaningful to have this later
 	raise_bottom_panel_item(AnimationPlayerEditor::singleton);