From 6ce47d9b51f6f540a8d3b6aece32ec0efdf2a37f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20J=2E=20Est=C3=A9banez?= Date: Mon, 27 Jun 2016 10:32:14 +0200 Subject: [PATCH 01/63] Improve parallax mirroring algorithm Replaces the iterative approach currently used by an equivalent direct computation. Also fixes infinite looping that happens when the mirroring value is negative. --- scene/2d/parallax_layer.cpp | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/scene/2d/parallax_layer.cpp b/scene/2d/parallax_layer.cpp index e9378b1d02f..05136de5d6c 100644 --- a/scene/2d/parallax_layer.cpp +++ b/scene/2d/parallax_layer.cpp @@ -123,26 +123,15 @@ void ParallaxLayer::set_base_offset_and_scale(const Point2& p_offset,float p_sca Point2 new_ofs = ((orig_offset+p_offset)*motion_scale)*p_scale+motion_offset; if (mirroring.x) { - - while( new_ofs.x>=0) { - new_ofs.x -= mirroring.x*p_scale; - } - while(new_ofs.x < -mirroring.x*p_scale) { - new_ofs.x += mirroring.x*p_scale; - } + double den = mirroring.x*p_scale; + new_ofs.x -= den*ceil(new_ofs.x/den); } if (mirroring.y) { - - while( new_ofs.y>=0) { - new_ofs.y -= mirroring.y*p_scale; - } - while(new_ofs.y < -mirroring.y*p_scale) { - new_ofs.y += mirroring.y*p_scale; - } + double den = mirroring.y*p_scale; + new_ofs.y -= den*ceil(new_ofs.y/den); } - set_pos(new_ofs); set_scale(Vector2(1,1)*p_scale); From 96eb97cbbf8acd38a44ecb914e12aeda322d0bd4 Mon Sep 17 00:00:00 2001 From: Pawel Kowal Date: Sat, 2 Jul 2016 19:03:35 +0200 Subject: [PATCH 02/63] Array has(var value) function --- core/array.cpp | 4 ++++ core/array.h | 1 + core/variant_call.cpp | 2 ++ 3 files changed, 7 insertions(+) diff --git a/core/array.cpp b/core/array.cpp index bb8e527304f..23792f90fc4 100644 --- a/core/array.cpp +++ b/core/array.cpp @@ -200,6 +200,10 @@ int Array::count(const Variant& p_value) const { return amount; } +bool Array::has(const Variant& p_value) const { + return _p->array.find(p_value, 0) != -1; +} + void Array::remove(int p_pos) { _p->array.remove(p_pos); diff --git a/core/array.h b/core/array.h index 096660653e6..dfc902525c9 100644 --- a/core/array.h +++ b/core/array.h @@ -75,6 +75,7 @@ public: int rfind(const Variant& p_value, int p_from=-1) const; int find_last(const Variant& p_value) const; int count(const Variant& p_value) const; + bool has(const Variant& p_value) const; void erase(const Variant& p_value); diff --git a/core/variant_call.cpp b/core/variant_call.cpp index a5927bb6f8e..a56627970b8 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -474,6 +474,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var VCALL_LOCALMEM2R(Array,rfind); VCALL_LOCALMEM1R(Array,find_last); VCALL_LOCALMEM1R(Array,count); + VCALL_LOCALMEM1R(Array,has); VCALL_LOCALMEM1(Array,erase); VCALL_LOCALMEM0(Array,sort); VCALL_LOCALMEM2(Array,sort_custom); @@ -1516,6 +1517,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl ADDFUNC2(ARRAY,INT,Array,rfind,NIL,"what",INT,"from",varray(-1)); ADDFUNC1(ARRAY,INT,Array,find_last,NIL,"value",varray()); ADDFUNC1(ARRAY,INT,Array,count,NIL,"value",varray()); + ADDFUNC1(ARRAY,BOOL,Array,has,NIL,"value",varray()); ADDFUNC0(ARRAY,NIL,Array,pop_back,varray()); ADDFUNC0(ARRAY,NIL,Array,pop_front,varray()); ADDFUNC0(ARRAY,NIL,Array,sort,varray()); From 3698332f6be935a918a9afbba62abd1a7952f509 Mon Sep 17 00:00:00 2001 From: Ovnuniarchos Date: Sun, 17 Jul 2016 01:58:28 +0200 Subject: [PATCH 03/63] Exposed mode, access, filters, and show hidden files to the editor. Also, two functions to get/set the filter list. --- scene/gui/file_dialog.cpp | 19 ++++++++++++++++++- scene/gui/file_dialog.h | 2 ++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index d335399caa9..6b43425edc8 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -475,7 +475,7 @@ void FileDialog::update_filters() { String flt=filters[i].get_slice(";",0).strip_edges(); String desc=filters[i].get_slice(";",1).strip_edges(); if (desc.length()) - filter->add_item(desc+" ( "+flt+" )"); + filter->add_item(String(XL_MESSAGE(desc))+" ( "+flt+" )"); else filter->add_item("( "+flt+" )"); } @@ -498,6 +498,16 @@ void FileDialog::add_filter(const String& p_filter) { } +void FileDialog::set_filters(const Vector& p_filters){ + filters=p_filters; + update_filters(); + invalidate(); +} + +Vector FileDialog::get_filters() const{ + return filters; +} + String FileDialog::get_current_dir() const { return dir->get_text(); @@ -686,6 +696,8 @@ void FileDialog::_bind_methods() { ObjectTypeDB::bind_method(_MD("clear_filters"),&FileDialog::clear_filters); ObjectTypeDB::bind_method(_MD("add_filter","filter"),&FileDialog::add_filter); + ObjectTypeDB::bind_method(_MD("set_filters","filters"),&FileDialog::set_filters); + ObjectTypeDB::bind_method(_MD("get_filters"),&FileDialog::get_filters); ObjectTypeDB::bind_method(_MD("get_current_dir"),&FileDialog::get_current_dir); ObjectTypeDB::bind_method(_MD("get_current_file"),&FileDialog::get_current_file); ObjectTypeDB::bind_method(_MD("get_current_path"),&FileDialog::get_current_path); @@ -722,6 +734,11 @@ void FileDialog::_bind_methods() { BIND_CONSTANT( ACCESS_USERDATA ); BIND_CONSTANT( ACCESS_FILESYSTEM ); + ADD_PROPERTY( PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Open one,Open many,Open folder,Open any,Save"),_SCS("set_mode"),_SCS("get_mode") ); + ADD_PROPERTY( PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User data,File system"),_SCS("set_access"),_SCS("get_access") ); + ADD_PROPERTY( PropertyInfo(Variant::STRING_ARRAY, "filters"),_SCS("set_filters"),_SCS("get_filters") ); + ADD_PROPERTY( PropertyInfo(Variant::BOOL, "show_hidden_files"),_SCS("set_show_hidden_files"),_SCS("is_showing_hidden_files") ); + } diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h index 1fcf8387cea..150b24cb3f9 100644 --- a/scene/gui/file_dialog.h +++ b/scene/gui/file_dialog.h @@ -131,6 +131,8 @@ public: void clear_filters(); void add_filter(const String& p_filter); + void set_filters(const Vector& p_filters); + Vector get_filters() const; void set_enable_multiple_selection(bool p_enable); Vector get_selected_files() const; From f26f181ba964d4fa4903ab936c26a27c65a1e525 Mon Sep 17 00:00:00 2001 From: volzhs Date: Sun, 26 Jun 2016 02:37:50 +0900 Subject: [PATCH 04/63] Fix can't get all info if user purchases many items and not consumed --- .../godot/payments/PaymentsManager.java | 76 +++++++++---------- 1 file changed, 34 insertions(+), 42 deletions(-) diff --git a/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java b/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java index eb33b37ecc4..35676e333e4 100644 --- a/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java +++ b/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java @@ -144,57 +144,49 @@ public class PaymentsManager { } }.consumeItAll(); } - - public void requestPurchased(){ - try{ + + public void requestPurchased() { + try { PaymentsCache pc = new PaymentsCache(Godot.getInstance()); -// Log.d("godot", "requestPurchased for " + activity.getPackageName()); - Bundle bundle = mService.getPurchases(3, activity.getPackageName(), "inapp",null); + String continueToken = null; -/* - for (String key : bundle.keySet()) { - Object value = bundle.get(key); - Log.d("godot", String.format("%s %s (%s)", key, value.toString(), value.getClass().getName())); - } -*/ - - if (bundle.getInt("RESPONSE_CODE") == 0){ + do { + Bundle bundle = mService.getPurchases(3, activity.getPackageName(), "inapp", continueToken); - final ArrayList myPurchases = bundle.getStringArrayList("INAPP_PURCHASE_DATA_LIST"); - final ArrayList mySignatures = bundle.getStringArrayList("INAPP_DATA_SIGNATURE_LIST"); - + if (bundle.getInt("RESPONSE_CODE") == 0) { - if (myPurchases == null || myPurchases.size() == 0){ -// Log.d("godot", "No purchases!"); - godotPaymentV3.callbackPurchased("", "", ""); - return; - } - -// Log.d("godot", "# products are purchased:" + myPurchases.size()); - for (int i=0;i myPurchases = bundle.getStringArrayList("INAPP_PURCHASE_DATA_LIST"); + final ArrayList mySignatures = bundle.getStringArrayList("INAPP_DATA_SIGNATURE_LIST"); - pc.setConsumableValue("ticket_signautre", sku, signature); - pc.setConsumableValue("ticket", sku, receipt); - pc.setConsumableFlag("block", sku, true); - pc.setConsumableValue("token", sku, token); + if (myPurchases == null || myPurchases.size() == 0) { + godotPaymentV3.callbackPurchased("", "", ""); + return; + } - godotPaymentV3.callbackPurchased(receipt, signature, sku); - } catch (JSONException e) { + for (int i = 0; i < myPurchases.size(); i++) { + + try { + String receipt = myPurchases.get(i); + JSONObject inappPurchaseData = new JSONObject(receipt); + String sku = inappPurchaseData.getString("productId"); + String token = inappPurchaseData.getString("purchaseToken"); + String signature = mySignatures.get(i); + + pc.setConsumableValue("ticket_signautre", sku, signature); + pc.setConsumableValue("ticket", sku, receipt); + pc.setConsumableFlag("block", sku, true); + pc.setConsumableValue("token", sku, token); + + godotPaymentV3.callbackPurchased(receipt, signature, sku); + } catch (JSONException e) { + } } } - - } - }catch(Exception e){ + continueToken = bundle.getString("INAPP_CONTINUATION_TOKEN"); + Log.d("godot", "continue token = " + continueToken); + } while (!TextUtils.isEmpty(continueToken)); + } catch (Exception e) { Log.d("godot", "Error requesting purchased products:" + e.getClass().getName() + ":" + e.getMessage()); } } From 79cb91dc842eded0fcbb562f127996759abeddc7 Mon Sep 17 00:00:00 2001 From: volzhs Date: Sun, 26 Jun 2016 02:46:40 +0900 Subject: [PATCH 05/63] Add querying details of IAP items for android --- .../org/godotengine/godot/GodotPaymentV3.java | 176 +++++++----- .../godot/payments/PaymentsManager.java | 259 ++++++++++++------ 2 files changed, 283 insertions(+), 152 deletions(-) diff --git a/platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java b/platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java index fde752acc99..b7de31ada37 100644 --- a/platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java +++ b/platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java @@ -28,99 +28,94 @@ /*************************************************************************/ package org.godotengine.godot; -import org.godotengine.godot.Dictionary; import android.app.Activity; import android.util.Log; +import org.godotengine.godot.payments.PaymentsManager; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + public class GodotPaymentV3 extends Godot.SingletonBase { private Godot activity; - private Integer purchaseCallbackId = 0; - private String accessToken; - private String purchaseValidationUrlPrefix; - private String transactionId; + private PaymentsManager mPaymentManager; + private Dictionary mSkuDetails = new Dictionary(); - public void purchase( String _sku, String _transactionId) { - final String sku = _sku; - final String transactionId = _transactionId; - activity.getPaymentsManager().setBaseSingleton(this); + public void purchase(final String sku, final String transactionId) { activity.runOnUiThread(new Runnable() { @Override public void run() { - activity.getPaymentsManager().requestPurchase(sku, transactionId); + mPaymentManager.requestPurchase(sku, transactionId); } }); } - -/* public string requestPurchasedTicket(){ - activity.getPaymentsManager() + + static public Godot.SingletonBase initialize(Activity p_activity) { + + return new GodotPaymentV3(p_activity); } -*/ - static public Godot.SingletonBase initialize(Activity p_activity) { - - return new GodotPaymentV3(p_activity); - } - - public GodotPaymentV3(Activity p_activity) { - registerClass("GodotPayments", new String[] {"purchase", "setPurchaseCallbackId", "setPurchaseValidationUrlPrefix", "setTransactionId", "getSignature", "consumeUnconsumedPurchases", "requestPurchased", "setAutoConsume", "consume"}); - activity=(Godot) p_activity; + registerClass("GodotPayments", new String[]{"purchase", "setPurchaseCallbackId", "setPurchaseValidationUrlPrefix", "setTransactionId", "getSignature", "consumeUnconsumedPurchases", "requestPurchased", "setAutoConsume", "consume", "querySkuDetails"}); + activity = (Godot) p_activity; + mPaymentManager = activity.getPaymentsManager(); + mPaymentManager.setBaseSingleton(this); } - public void consumeUnconsumedPurchases(){ - activity.getPaymentsManager().setBaseSingleton(this); + public void consumeUnconsumedPurchases() { activity.runOnUiThread(new Runnable() { @Override public void run() { - activity.getPaymentsManager().consumeUnconsumedPurchases(); + mPaymentManager.consumeUnconsumedPurchases(); } }); } private String signature; - public String getSignature(){ - return this.signature; + + public String getSignature() { + return this.signature; } - - - public void callbackSuccess(String ticket, String signature, String sku){ -// Log.d(this.getClass().getName(), "PRE-Send callback to purchase success"); + + public void callbackSuccess(String ticket, String signature, String sku) { GodotLib.callobject(purchaseCallbackId, "purchase_success", new Object[]{ticket, signature, sku}); -// Log.d(this.getClass().getName(), "POST-Send callback to purchase success"); -} - - public void callbackSuccessProductMassConsumed(String ticket, String signature, String sku){ -// Log.d(this.getClass().getName(), "PRE-Send callback to consume success"); - Log.d(this.getClass().getName(), "callbackSuccessProductMassConsumed > "+ticket+","+signature+","+sku); - GodotLib.calldeferred(purchaseCallbackId, "consume_success", new Object[]{ticket, signature, sku}); -// Log.d(this.getClass().getName(), "POST-Send callback to consume success"); } - public void callbackSuccessNoUnconsumedPurchases(){ - GodotLib.calldeferred(purchaseCallbackId, "no_validation_required", new Object[]{}); + public void callbackSuccessProductMassConsumed(String ticket, String signature, String sku) { + Log.d(this.getClass().getName(), "callbackSuccessProductMassConsumed > " + ticket + "," + signature + "," + sku); + GodotLib.calldeferred(purchaseCallbackId, "consume_success", new Object[]{ticket, signature, sku}); } - - public void callbackFail(){ + + public void callbackSuccessNoUnconsumedPurchases() { + GodotLib.calldeferred(purchaseCallbackId, "consume_not_required", new Object[]{}); + } + + public void callbackFailConsume() { + GodotLib.calldeferred(purchaseCallbackId, "consume_fail", new Object[]{}); + } + + public void callbackFail() { GodotLib.calldeferred(purchaseCallbackId, "purchase_fail", new Object[]{}); -// GodotLib.callobject(purchaseCallbackId, "purchase_fail", new Object[]{}); } - - public void callbackCancel(){ + + public void callbackCancel() { GodotLib.calldeferred(purchaseCallbackId, "purchase_cancel", new Object[]{}); -// GodotLib.callobject(purchaseCallbackId, "purchase_cancel", new Object[]{}); } - - public void callbackAlreadyOwned(String sku){ + + public void callbackAlreadyOwned(String sku) { GodotLib.calldeferred(purchaseCallbackId, "purchase_owned", new Object[]{sku}); } - + public int getPurchaseCallbackId() { return purchaseCallbackId; } @@ -129,11 +124,11 @@ public class GodotPaymentV3 extends Godot.SingletonBase { this.purchaseCallbackId = purchaseCallbackId; } - public String getPurchaseValidationUrlPrefix(){ - return this.purchaseValidationUrlPrefix ; + public String getPurchaseValidationUrlPrefix() { + return this.purchaseValidationUrlPrefix; } - public void setPurchaseValidationUrlPrefix(String url){ + public void setPurchaseValidationUrlPrefix(String url) { this.purchaseValidationUrlPrefix = url; } @@ -144,39 +139,80 @@ public class GodotPaymentV3 extends Godot.SingletonBase { public void setAccessToken(String accessToken) { this.accessToken = accessToken; } - - public void setTransactionId(String transactionId){ + + public void setTransactionId(String transactionId) { this.transactionId = transactionId; } - - public String getTransactionId(){ + + public String getTransactionId() { return this.transactionId; } - + // request purchased items are not consumed - public void requestPurchased(){ - activity.getPaymentsManager().setBaseSingleton(this); + public void requestPurchased() { activity.runOnUiThread(new Runnable() { @Override public void run() { - activity.getPaymentsManager().requestPurchased(); + mPaymentManager.requestPurchased(); } }); } - + // callback for requestPurchased() - public void callbackPurchased(String receipt, String signature, String sku){ + public void callbackPurchased(String receipt, String signature, String sku) { GodotLib.calldeferred(purchaseCallbackId, "has_purchased", new Object[]{receipt, signature, sku}); } - + // consume item automatically after purchase. default is true. - public void setAutoConsume(boolean autoConsume){ - activity.getPaymentsManager().setAutoConsume(autoConsume); + public void setAutoConsume(boolean autoConsume) { + mPaymentManager.setAutoConsume(autoConsume); } - + // consume a specific item - public void consume(String sku){ - activity.getPaymentsManager().consume(sku); + public void consume(String sku) { + mPaymentManager.consume(sku); + } + + // query in app item detail info + public void querySkuDetails(String[] list) { + List nKeys = Arrays.asList(list); + List cKeys = Arrays.asList(mSkuDetails.get_keys()); + ArrayList fKeys = new ArrayList(); + for (String key : nKeys) { + if (!cKeys.contains(key)) { + fKeys.add(key); + } + } + if (fKeys.size() > 0) { + mPaymentManager.querySkuDetails(fKeys.toArray(new String[0])); + } else { + completeSkuDetail(); + } + } + + public void addSkuDetail(String itemJson) { + JSONObject o = null; + try { + o = new JSONObject(itemJson); + Dictionary item = new Dictionary(); + item.put("type", o.optString("type")); + item.put("product_id", o.optString("productId")); + item.put("title", o.optString("title")); + item.put("description", o.optString("description")); + item.put("price", o.optString("price")); + item.put("price_currency_code", o.optString("price_currency_code")); + item.put("price_amount", 0.000001d * o.optLong("price_amount_micros")); + mSkuDetails.put(item.get("product_id").toString(), item); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + public void completeSkuDetail() { + GodotLib.calldeferred(purchaseCallbackId, "sku_details_complete", new Object[]{mSkuDetails}); + } + + public void errorSkuDetail(String errorMessage) { + GodotLib.calldeferred(purchaseCallbackId, "sku_details_error", new Object[]{errorMessage}); } } - diff --git a/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java b/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java index 35676e333e4..753c0a6f93a 100644 --- a/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java +++ b/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java @@ -28,119 +28,120 @@ /*************************************************************************/ package org.godotengine.godot.payments; -import java.util.ArrayList; -import java.util.List; - -import android.os.RemoteException; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; -import android.os.IBinder; -import android.util.Log; import android.os.Bundle; +import android.os.IBinder; +import android.os.RemoteException; +import android.text.TextUtils; +import android.util.Log; -import org.json.JSONException; -import org.json.JSONObject; -import org.json.JSONStringer; +import com.android.vending.billing.IInAppBillingService; -import org.godotengine.godot.Dictionary; import org.godotengine.godot.Godot; import org.godotengine.godot.GodotPaymentV3; -import com.android.vending.billing.IInAppBillingService; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.Arrays; public class PaymentsManager { public static final int BILLING_RESPONSE_RESULT_OK = 0; public static final int REQUEST_CODE_FOR_PURCHASE = 0x1001; private static boolean auto_consume = true; - + private Activity activity; IInAppBillingService mService; - public void setActivity(Activity activity){ + public void setActivity(Activity activity) { this.activity = activity; } - public static PaymentsManager createManager(Activity activity){ + public static PaymentsManager createManager(Activity activity) { PaymentsManager manager = new PaymentsManager(activity); return manager; } - - private PaymentsManager(Activity activity){ + + private PaymentsManager(Activity activity) { this.activity = activity; } - - public PaymentsManager initService(){ + + public PaymentsManager initService() { Intent intent = new Intent("com.android.vending.billing.InAppBillingService.BIND"); intent.setPackage("com.android.vending"); activity.bindService( - intent, - mServiceConn, + intent, + mServiceConn, Context.BIND_AUTO_CREATE); return this; } - public void destroy(){ + public void destroy() { if (mService != null) { - activity.unbindService(mServiceConn); - } + activity.unbindService(mServiceConn); + } } - - ServiceConnection mServiceConn = new ServiceConnection() { - @Override - public void onServiceDisconnected(ComponentName name) { - mService = null; - } - @Override - public void onServiceConnected(ComponentName name, IBinder service) { + ServiceConnection mServiceConn = new ServiceConnection() { + @Override + public void onServiceDisconnected(ComponentName name) { + mService = null; + } + + @Override + public void onServiceConnected(ComponentName name, IBinder service) { mService = IInAppBillingService.Stub.asInterface(service); - } + } }; - - public void requestPurchase(final String sku, String transactionId){ + + public void requestPurchase(final String sku, String transactionId) { new PurchaseTask(mService, Godot.getInstance()) { - + @Override protected void error(String message) { godotPaymentV3.callbackFail(); - + } - + @Override protected void canceled() { godotPaymentV3.callbackCancel(); } - + @Override protected void alreadyOwned() { godotPaymentV3.callbackAlreadyOwned(sku); } - + }.purchase(sku, transactionId); } - public void consumeUnconsumedPurchases(){ + public void consumeUnconsumedPurchases() { new ReleaseAllConsumablesTask(mService, activity) { - + @Override protected void success(String sku, String receipt, String signature, String token) { godotPaymentV3.callbackSuccessProductMassConsumed(receipt, signature, sku); } - + @Override protected void error(String message) { - godotPaymentV3.callbackFail(); - + Log.d("godot", "consumeUnconsumedPurchases :" + message); + godotPaymentV3.callbackFailConsume(); + } @Override protected void notRequired() { + Log.d("godot", "callbackSuccessNoUnconsumedPurchases :"); godotPaymentV3.callbackSuccessNoUnconsumedPurchases(); - + } }.consumeItAll(); } @@ -190,113 +191,207 @@ public class PaymentsManager { Log.d("godot", "Error requesting purchased products:" + e.getClass().getName() + ":" + e.getMessage()); } } - + public void processPurchaseResponse(int resultCode, Intent data) { - new HandlePurchaseTask(activity){ + new HandlePurchaseTask(activity) { @Override protected void success(final String sku, final String signature, final String ticket) { godotPaymentV3.callbackSuccess(ticket, signature, sku); - if (auto_consume){ + if (auto_consume) { new ConsumeTask(mService, activity) { - + @Override protected void success(String ticket) { -// godotPaymentV3.callbackSuccess(""); } - + @Override protected void error(String message) { godotPaymentV3.callbackFail(); - + } }.consume(sku); } - -// godotPaymentV3.callbackSuccess(new PaymentsCache(activity).getConsumableValue("ticket", sku),signature); -// godotPaymentV3.callbackSuccess(ticket); - //validatePurchase(purchaseToken, sku); } @Override protected void error(String message) { godotPaymentV3.callbackFail(); - } @Override protected void canceled() { godotPaymentV3.callbackCancel(); - } }.handlePurchaseRequest(resultCode, data); } - - public void validatePurchase(String purchaseToken, final String sku){ - - new ValidateTask(activity, godotPaymentV3){ + + public void validatePurchase(String purchaseToken, final String sku) { + + new ValidateTask(activity, godotPaymentV3) { @Override protected void success() { - + new ConsumeTask(mService, activity) { - + @Override protected void success(String ticket) { godotPaymentV3.callbackSuccess(ticket, null, sku); - } - + @Override protected void error(String message) { godotPaymentV3.callbackFail(); - } }.consume(sku); - + } @Override protected void error(String message) { godotPaymentV3.callbackFail(); - } @Override protected void canceled() { godotPaymentV3.callbackCancel(); - } }.validatePurchase(sku); } - - public void setAutoConsume(boolean autoConsume){ + + public void setAutoConsume(boolean autoConsume) { auto_consume = autoConsume; } - - public void consume(final String sku){ + + public void consume(final String sku) { new ConsumeTask(mService, activity) { - + @Override protected void success(String ticket) { godotPaymentV3.callbackSuccessProductMassConsumed(ticket, "", sku); - } - + @Override protected void error(String message) { - godotPaymentV3.callbackFail(); - + godotPaymentV3.callbackFailConsume(); } }.consume(sku); } - + + // Workaround to bug where sometimes response codes come as Long instead of Integer + int getResponseCodeFromBundle(Bundle b) { + Object o = b.get("RESPONSE_CODE"); + if (o == null) { + //logDebug("Bundle with null response code, assuming OK (known issue)"); + return BILLING_RESPONSE_RESULT_OK; + } else if (o instanceof Integer) return ((Integer) o).intValue(); + else if (o instanceof Long) return (int) ((Long) o).longValue(); + else { + //logError("Unexpected type for bundle response code."); + //logError(o.getClass().getName()); + throw new RuntimeException("Unexpected type for bundle response code: " + o.getClass().getName()); + } + } + + /** + * Returns a human-readable description for the given response code. + * + * @param code The response code + * @return A human-readable string explaining the result code. + * It also includes the result code numerically. + */ + public static String getResponseDesc(int code) { + String[] iab_msgs = ("0:OK/1:User Canceled/2:Unknown/" + + "3:Billing Unavailable/4:Item unavailable/" + + "5:Developer Error/6:Error/7:Item Already Owned/" + + "8:Item not owned").split("/"); + String[] iabhelper_msgs = ("0:OK/-1001:Remote exception during initialization/" + + "-1002:Bad response received/" + + "-1003:Purchase signature verification failed/" + + "-1004:Send intent failed/" + + "-1005:User cancelled/" + + "-1006:Unknown purchase response/" + + "-1007:Missing token/" + + "-1008:Unknown error/" + + "-1009:Subscriptions not available/" + + "-1010:Invalid consumption attempt").split("/"); + + if (code <= -1000) { + int index = -1000 - code; + if (index >= 0 && index < iabhelper_msgs.length) return iabhelper_msgs[index]; + else return String.valueOf(code) + ":Unknown IAB Helper Error"; + } else if (code < 0 || code >= iab_msgs.length) + return String.valueOf(code) + ":Unknown"; + else + return iab_msgs[code]; + } + + public void querySkuDetails(final String[] list) { + (new Thread(new Runnable() { + @Override + public void run() { + ArrayList skuList = new ArrayList(Arrays.asList(list)); + if (skuList.size() == 0) { + return; + } + // Split the sku list in blocks of no more than 20 elements. + ArrayList> packs = new ArrayList>(); + ArrayList tempList; + int n = skuList.size() / 20; + int mod = skuList.size() % 20; + for (int i = 0; i < n; i++) { + tempList = new ArrayList(); + for (String s : skuList.subList(i * 20, i * 20 + 20)) { + tempList.add(s); + } + packs.add(tempList); + } + if (mod != 0) { + tempList = new ArrayList(); + for (String s : skuList.subList(n * 20, n * 20 + mod)) { + tempList.add(s); + } + packs.add(tempList); + + for (ArrayList skuPartList : packs) { + Bundle querySkus = new Bundle(); + querySkus.putStringArrayList("ITEM_ID_LIST", skuPartList); + Bundle skuDetails = null; + try { + skuDetails = mService.getSkuDetails(3, activity.getPackageName(), "inapp", querySkus); + if (!skuDetails.containsKey("DETAILS_LIST")) { + int response = getResponseCodeFromBundle(skuDetails); + if (response != BILLING_RESPONSE_RESULT_OK) { + godotPaymentV3.errorSkuDetail(getResponseDesc(response)); + } else { + godotPaymentV3.errorSkuDetail("No error but no detail list."); + } + return; + } + + ArrayList responseList = skuDetails.getStringArrayList("DETAILS_LIST"); + + for (String thisResponse : responseList) { + Log.d("godot", "response = "+thisResponse); + godotPaymentV3.addSkuDetail(thisResponse); + } + } catch (RemoteException e) { + e.printStackTrace(); + godotPaymentV3.errorSkuDetail("RemoteException error!"); + } + } + godotPaymentV3.completeSkuDetail(); + } + } + })).start(); + } + private GodotPaymentV3 godotPaymentV3; - + public void setBaseSingleton(GodotPaymentV3 godotPaymentV3) { this.godotPaymentV3 = godotPaymentV3; } } - From 1e7b9c509f02dd641f10fe50d24bb19c165078d7 Mon Sep 17 00:00:00 2001 From: Jaroslaw Filiochowski Date: Mon, 18 Jul 2016 22:14:57 +0200 Subject: [PATCH 06/63] Don't start a new tooltip timer for the same tooltip --- scene/main/viewport.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index bb6e6e289b9..9d2b0cfccfd 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -2007,8 +2007,16 @@ void Viewport::_gui_input_event(InputEvent p_event) { } + bool is_tooltip_shown = false; - if (can_tooltip) { + if (can_tooltip && gui.tooltip_popup) { + String tooltip = over->get_tooltip(gui.tooltip->get_global_transform().xform_inv(mpos)); + + if (gui.tooltip_popup && tooltip == gui.tooltip_label->get_text()) + is_tooltip_shown = true; + } + + if (can_tooltip && !is_tooltip_shown) { gui.tooltip=over; gui.tooltip_pos=mpos;//(parent_xform * get_transform()).affine_inverse().xform(pos); From be560a750c363355ad077331bf6bdbc62c6b2762 Mon Sep 17 00:00:00 2001 From: Jaroslaw Filiochowski Date: Tue, 19 Jul 2016 06:27:12 +0200 Subject: [PATCH 07/63] Hide tooltip if new mouse position's tooltip is empty --- scene/main/viewport.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 9d2b0cfccfd..cf84f8f4251 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -2009,11 +2009,17 @@ void Viewport::_gui_input_event(InputEvent p_event) { bool is_tooltip_shown = false; - if (can_tooltip && gui.tooltip_popup) { - String tooltip = over->get_tooltip(gui.tooltip->get_global_transform().xform_inv(mpos)); + if (gui.tooltip_popup) { + if (can_tooltip) { + String tooltip = over->get_tooltip(gui.tooltip->get_global_transform().xform_inv(mpos)); - if (gui.tooltip_popup && tooltip == gui.tooltip_label->get_text()) - is_tooltip_shown = true; + if (tooltip.length() == 0) + _gui_cancel_tooltip(); + else if (tooltip == gui.tooltip_label->get_text()) + is_tooltip_shown = true; + } + else + _gui_cancel_tooltip(); } if (can_tooltip && !is_tooltip_shown) { From 2b608846594bc69a20f8945c6f61bdb9319b2fdb Mon Sep 17 00:00:00 2001 From: Algrin6 Date: Thu, 21 Jul 2016 02:14:58 +0300 Subject: [PATCH 08/63] Fix curve bug --- scene/resources/curve.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index 88ff09e961f..29460790ff7 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -644,7 +644,7 @@ Vector2 Curve2D::interpolate_baked(float p_offset,bool p_cubic) const{ if (p_offset>=baked_max_ofs) return r[bpc-1]; - int idx = Math::floor(p_offset/bake_interval); + int idx = Math::floor((double)p_offset/(double)bake_interval); float frac = Math::fmod(p_offset,bake_interval); if (idx>=bpc-1) { @@ -1117,7 +1117,7 @@ Vector3 Curve3D::interpolate_baked(float p_offset,bool p_cubic) const{ if (p_offset>=baked_max_ofs) return r[bpc-1]; - int idx = Math::floor(p_offset/bake_interval); + int idx = Math::floor((double)p_offset/(double)bake_interval); float frac = Math::fmod(p_offset,bake_interval); if (idx>=bpc-1) { @@ -1161,7 +1161,7 @@ float Curve3D::interpolate_baked_tilt(float p_offset) const{ if (p_offset>=baked_max_ofs) return r[bpc-1]; - int idx = Math::floor(p_offset/bake_interval); + int idx = Math::floor((double)p_offset/(double)bake_interval); float frac = Math::fmod(p_offset,bake_interval); if (idx>=bpc-1) { From fc16954fa2d87707fa69293b7507dd43b028a96f Mon Sep 17 00:00:00 2001 From: Ignacio Etcheverry Date: Thu, 21 Jul 2016 03:40:08 +0200 Subject: [PATCH 09/63] TextEdit: Center search results --- scene/gui/text_edit.cpp | 28 ++++++++++++++++++++++++++++ scene/gui/text_edit.h | 2 ++ tools/editor/code_editor.cpp | 5 +++-- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index a680d5d873e..98e6ee366e4 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -2984,6 +2984,34 @@ void TextEdit::adjust_viewport_to_cursor() { } +void TextEdit::center_viewport_to_cursor() { + + if (cursor.line_ofs>cursor.line) + cursor.line_ofs=cursor.line; + + int visible_width=cache.size.width-cache.style_normal->get_minimum_size().width-cache.line_number_w-cache.breakpoint_gutter_width; + if (v_scroll->is_visible()) + visible_width-=v_scroll->get_combined_minimum_size().width; + visible_width-=20; // give it a little more space + + int visible_rows = get_visible_rows(); + if (h_scroll->is_visible()) + visible_rows-=((h_scroll->get_combined_minimum_size().height-1)/get_row_height()); + + int max_ofs = text.size()-(scroll_past_end_of_file_enabled?1:visible_rows); + cursor.line_ofs=CLAMP(cursor.line-(visible_rows/2),0,max_ofs); + + int cursor_x = get_column_x_offset( cursor.column, text[cursor.line] ); + + if (cursor_x>(cursor.x_ofs+visible_width)) + cursor.x_ofs=cursor_x-visible_width+1; + + if (cursor_x < cursor.x_ofs) + cursor.x_ofs=cursor_x; + + update(); +} + void TextEdit::cursor_set_column(int p_col, bool p_adjust_viewport) { if (p_col<0) diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 270a1723b17..d67b3c998bb 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -394,6 +394,8 @@ public: } void set_auto_indent(bool p_auto_indent); + void center_viewport_to_cursor(); + void cursor_set_column(int p_col, bool p_adjust_viewport=true); void cursor_set_line(int p_row, bool p_adjust_viewport=true); diff --git a/tools/editor/code_editor.cpp b/tools/editor/code_editor.cpp index 71ae171dfeb..6c8d25aa01f 100644 --- a/tools/editor/code_editor.cpp +++ b/tools/editor/code_editor.cpp @@ -133,8 +133,9 @@ bool FindReplaceBar::_search(uint32_t p_flags, int p_from_line, int p_from_col) if (found) { if (!preserve_cursor) { - text_edit->cursor_set_line(line); - text_edit->cursor_set_column(col+text.length()); + text_edit->cursor_set_line(line, false); + text_edit->cursor_set_column(col+text.length(), false); + text_edit->center_viewport_to_cursor(); } text_edit->set_search_text(text); From 53beeb774b36b7af391e61fffeceb9f7ed3e299e Mon Sep 17 00:00:00 2001 From: Franklin Sobrinho Date: Wed, 20 Jul 2016 14:09:03 -0300 Subject: [PATCH 10/63] "FileSystem" dock now instance all selected scenes in one action --- tools/editor/editor_node.cpp | 10 +++++++--- tools/editor/editor_node.h | 3 ++- tools/editor/filesystem_dock.cpp | 10 ++++++++-- tools/editor/scene_tree_dock.cpp | 25 ++++++++++++++++++++++--- tools/editor/scene_tree_dock.h | 4 +++- 5 files changed, 42 insertions(+), 10 deletions(-) diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 3f93c059197..42c81c68f55 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -3822,6 +3822,11 @@ void EditorNode::request_instance_scene(const String &p_path) { } +void EditorNode::request_instance_scenes(const Vector& p_files) { + + scene_tree_dock->instance_scenes(p_files); +} + FileSystemDock *EditorNode::get_scenes_dock() { return scenes_dock; @@ -3831,10 +3836,9 @@ SceneTreeDock *EditorNode::get_scene_tree_dock() { return scene_tree_dock; } -void EditorNode::_instance_request(const String& p_path){ +void EditorNode::_instance_request(const Vector& p_files) { - - request_instance_scene(p_path); + request_instance_scenes(p_files); } void EditorNode::_property_keyed(const String& p_keyed,const Variant& p_value,bool p_advance) { diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h index 9a227d36442..793c1486710 100644 --- a/tools/editor/editor_node.h +++ b/tools/editor/editor_node.h @@ -452,7 +452,7 @@ private: void _save_scene(String p_file, int idx = -1); - void _instance_request(const String& p_path); + void _instance_request(const Vector& p_files); void _property_keyed(const String& p_keyed, const Variant& p_value, bool p_advance); void _transform_keyed(Object *sp,const String& p_sub,const Transform& p_key); @@ -666,6 +666,7 @@ public: static VSplitContainer *get_top_split() { return singleton->top_split; } void request_instance_scene(const String &p_path); + void request_instance_scenes(const Vector& p_files); FileSystemDock *get_scenes_dock(); SceneTreeDock *get_scene_tree_dock(); static UndoRedo* get_undo_redo() { return &singleton->editor_data.get_undo_redo(); } diff --git a/tools/editor/filesystem_dock.cpp b/tools/editor/filesystem_dock.cpp index 3be122cc7d6..378edd6667b 100644 --- a/tools/editor/filesystem_dock.cpp +++ b/tools/editor/filesystem_dock.cpp @@ -950,14 +950,20 @@ void FileSystemDock::_file_option(int p_option) { } break; case FILE_INSTANCE: { + Vector paths; + for (int i = 0; iget_item_count(); i++) { if (!files->is_selected(i)) continue; String path =files->get_item_metadata(i); if (EditorFileSystem::get_singleton()->get_file_type(path)=="PackedScene") { - emit_signal("instance",path); + paths.push_back(path); } } + + if (!paths.empty()) { + emit_signal("instance", paths); + } } break; case FILE_DEPENDENCIES: { @@ -1596,7 +1602,7 @@ void FileSystemDock::_bind_methods() { ObjectTypeDB::bind_method(_MD("_preview_invalidated"),&FileSystemDock::_preview_invalidated); - ADD_SIGNAL(MethodInfo("instance")); + ADD_SIGNAL(MethodInfo("instance", PropertyInfo(Variant::STRING_ARRAY, "files"))); ADD_SIGNAL(MethodInfo("open")); } diff --git a/tools/editor/scene_tree_dock.cpp b/tools/editor/scene_tree_dock.cpp index e4dfcc0f626..a3dec57882d 100644 --- a/tools/editor/scene_tree_dock.cpp +++ b/tools/editor/scene_tree_dock.cpp @@ -106,11 +106,30 @@ void SceneTreeDock::instance(const String& p_file) { Vector scenes; scenes.push_back(p_file); - instance_scenes(scenes,parent,-1); + _perform_instance_scenes(scenes,parent,-1); } -void SceneTreeDock::instance_scenes(const Vector& p_files,Node* parent,int p_pos) { +void SceneTreeDock::instance_scenes(const Vector& p_files, Node *p_parent) { + + Node *parent = p_parent; + + if (!parent) { + parent = scene_tree->get_selected(); + } + + if (!parent || !edited_scene) { + + accept->get_ok()->set_text(TTR("OK")); + accept->set_text(TTR("No parent to instance the scenes at.")); + accept->popup_centered_minsize(); + return; + }; + + _perform_instance_scenes(p_files, parent, -1); +} + +void SceneTreeDock::_perform_instance_scenes(const Vector& p_files,Node* parent,int p_pos) { @@ -1677,7 +1696,7 @@ void SceneTreeDock::_files_dropped(Vector p_files,NodePath p_to,int p_ty int to_pos=-1; _normalize_drop(node,to_pos,p_type); - instance_scenes(p_files,node,to_pos); + _perform_instance_scenes(p_files,node,to_pos); } void SceneTreeDock::_nodes_dragged(Array p_nodes,NodePath p_to,int p_type) { diff --git a/tools/editor/scene_tree_dock.h b/tools/editor/scene_tree_dock.h index 51041a235bd..04ed16967ff 100644 --- a/tools/editor/scene_tree_dock.h +++ b/tools/editor/scene_tree_dock.h @@ -148,6 +148,8 @@ class SceneTreeDock : public VBoxContainer { void _filter_changed(const String& p_filter); + void _perform_instance_scenes(const Vector& p_files,Node* parent,int p_pos); + protected: void _notification(int p_what); @@ -160,7 +162,7 @@ public: void import_subscene(); void set_edited_scene(Node* p_scene); void instance(const String& p_path); - void instance_scenes(const Vector& p_files,Node* parent,int p_pos); + void instance_scenes(const Vector& p_files, Node *p_parent=NULL); void set_selected(Node *p_node, bool p_emit_selected=false); void fill_path_renames(Node* p_node, Node *p_new_parent, List > *p_renames); void perform_node_renames(Node* p_base,List > *p_renames, Map, Set > *r_rem_anims=NULL); From f46f5306260f9a3e0bb04a99bd1b575580441149 Mon Sep 17 00:00:00 2001 From: Alex Piola Date: Fri, 22 Jul 2016 14:27:03 +0200 Subject: [PATCH 11/63] Fix #5854 Fix for #5854 --- servers/physics/body_pair_sw.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/servers/physics/body_pair_sw.cpp b/servers/physics/body_pair_sw.cpp index 3202e52abb0..06c728ea499 100644 --- a/servers/physics/body_pair_sw.cpp +++ b/servers/physics/body_pair_sw.cpp @@ -323,14 +323,14 @@ bool BodyPairSW::setup(float p_step) { #endif if (A->can_report_contacts()) { - Vector3 crB = A->get_angular_velocity().cross( c.rA ) + A->get_linear_velocity(); - A->add_contact(global_A,-c.normal,depth,shape_A,global_B,shape_B,B->get_instance_id(),B->get_self(),crB); - } + Vector3 crA = A->get_angular_velocity().cross( c.rA ) + A->get_linear_velocity(); + A->add_contact(global_A,-c.normal,depth,shape_A,global_B,shape_B,B->get_instance_id(),B->get_self(),crA); + } - if (B->can_report_contacts()) { - Vector3 crA = A->get_angular_velocity().cross( c.rB ) + A->get_linear_velocity(); - B->add_contact(global_B,c.normal,depth,shape_B,global_A,shape_A,A->get_instance_id(),A->get_self(),crA); - } + if (B->can_report_contacts()) { + Vector3 crB = B->get_angular_velocity().cross( c.rB ) + B->get_linear_velocity(); + B->add_contact(global_B,c.normal,depth,shape_B,global_A,shape_A,A->get_instance_id(),A->get_self(),crB); + } if (A->is_shape_set_as_trigger(shape_A) || B->is_shape_set_as_trigger(shape_B) || (A->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC && B->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC)) { c.active=false; From 5d52146ff783e8966562b1feb144ef1fee03a6f5 Mon Sep 17 00:00:00 2001 From: Johan Manuel Date: Sat, 23 Jul 2016 14:47:49 +0200 Subject: [PATCH 12/63] Fix warnings in core/variant_op.cpp Adds default cases in switches where needed, and replaces '0;' with ';;' in macro expansions (as suggested by @vnen in #5587). --- core/variant_op.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/core/variant_op.cpp b/core/variant_op.cpp index 9182dcde1a5..c537ed230fc 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -600,6 +600,7 @@ void Variant::evaluate(const Operator& p_op, const Variant& p_a, const Variant& case REAL: { _RETURN( *reinterpret_cast(p_a._data._mem) * p_b._data._real); } break; + default: {} }; r_valid=false; return; @@ -618,6 +619,7 @@ void Variant::evaluate(const Operator& p_op, const Variant& p_a, const Variant& _RETURN( *p_a._data._matrix3 * *p_b._data._matrix3 ); }; + default: {} } ; r_valid=false; return; @@ -635,6 +637,7 @@ void Variant::evaluate(const Operator& p_op, const Variant& p_a, const Variant& _RETURN( *p_a._data._transform * *p_b._data._transform ); }; + default: {} } ; r_valid=false; return; @@ -999,7 +1002,7 @@ Variant Variant::get_named(const StringName& p_index, bool *r_valid) const { DEFAULT_OP_ARRAY_CMD(m_name, DVector, if(skip_cond) return;, arr->set(index, p_value);return) #define DEFAULT_OP_DVECTOR_GET(m_name, dv_type)\ - DEFAULT_OP_ARRAY_CMD(m_name, const DVector, 0, return arr->get(index)) + DEFAULT_OP_ARRAY_CMD(m_name, const DVector, ;, return arr->get(index)) void Variant::set(const Variant& p_index, const Variant& p_value, bool *r_valid) { @@ -2417,7 +2420,7 @@ Variant Variant::get(const Variant& p_index, bool *r_valid) const { return *res; } } break; // 20 - DEFAULT_OP_ARRAY_CMD(ARRAY, const Array, 0, return (*arr)[index]) + DEFAULT_OP_ARRAY_CMD(ARRAY, const Array, ;, return (*arr)[index]) DEFAULT_OP_DVECTOR_GET(RAW_ARRAY, uint8_t) DEFAULT_OP_DVECTOR_GET(INT_ARRAY, int) DEFAULT_OP_DVECTOR_GET(REAL_ARRAY, real_t) @@ -2994,6 +2997,7 @@ bool Variant::iter_init(Variant& r_iter,bool &valid) const { return true; } break; + default: {} } @@ -3137,6 +3141,7 @@ bool Variant::iter_next(Variant& r_iter,bool &valid) const { r_iter=idx; return true; } break; + default: {} } @@ -3279,6 +3284,7 @@ Variant Variant::iter_get(const Variant& r_iter,bool &r_valid) const { #endif return arr->get(idx); } break; + default: {} } From 761193ecd9ac0240fc8bf945f0601acb82bf8e98 Mon Sep 17 00:00:00 2001 From: Ignacio Etcheverry Date: Sat, 23 Jul 2016 21:37:25 +0200 Subject: [PATCH 13/63] Project Manager: Added project list scrolling with keyboard --- tools/editor/project_manager.cpp | 134 +++++++++++++++++++++++++++++++ tools/editor/project_manager.h | 1 + 2 files changed, 135 insertions(+) diff --git a/tools/editor/project_manager.cpp b/tools/editor/project_manager.cpp index b7d3abfd5b9..caf116523ae 100644 --- a/tools/editor/project_manager.cpp +++ b/tools/editor/project_manager.cpp @@ -31,6 +31,7 @@ #include "os/os.h" #include "os/dir_access.h" #include "os/file_access.h" +#include "os/keyboard.h" #include "editor_settings.h" #include "scene/gui/separator.h" #include "scene/gui/tool_button.h" @@ -491,6 +492,10 @@ void ProjectManager::_notification(int p_what) { if (p_what==NOTIFICATION_ENTER_TREE) { get_tree()->set_editor_hint(true); + + } else if (p_what==NOTIFICATION_VISIBILITY_CHANGED) { + + set_process_unhandled_input(is_visible()); } } @@ -576,6 +581,134 @@ void ProjectManager::_panel_input(const InputEvent& p_ev,Node *p_hb) { } } +void ProjectManager::_unhandled_input(const InputEvent& p_ev) { + + if (p_ev.type==InputEvent::KEY) { + + const InputEventKey &k = p_ev.key; + + if (!k.pressed) + return; + + bool scancode_handled = true; + + switch (k.scancode) { + + case KEY_HOME: { + + for (int i=0; iget_child_count(); i++) { + + HBoxContainer *hb = scroll_childs->get_child(i)->cast_to(); + if (hb) { + selected_list.clear(); + selected_list.insert(hb->get_meta("name"), hb->get_meta("main_scene")); + scroll->set_v_scroll(0); + break; + } + } + + } break; + case KEY_END: { + + for (int i=scroll_childs->get_child_count()-1; i>=0; i--) { + + HBoxContainer *hb = scroll_childs->get_child(i)->cast_to(); + if (hb) { + selected_list.clear(); + selected_list.insert(hb->get_meta("name"), hb->get_meta("main_scene")); + scroll->set_v_scroll(scroll_childs->get_size().y); + break; + } + } + + } break; + case KEY_UP: { + + if (k.mod.shift) + break; + + if (selected_list.size()) { + + bool found = false; + + for (int i=scroll_childs->get_child_count()-1; i>=0; i--) { + + HBoxContainer *hb = scroll_childs->get_child(i)->cast_to(); + if (!hb) continue; + + String current = hb->get_meta("name"); + + if (found) { + selected_list.clear(); + selected_list.insert(current, hb->get_meta("main_scene")); + + int offset_diff = scroll->get_v_scroll() - hb->get_pos().y; + + if (offset_diff > 0) + scroll->set_v_scroll(scroll->get_v_scroll() - offset_diff); + + break; + + } else if (current==selected_list.back()->key()) { + + found = true; + } + } + + break; + } + // else fallthrough to key_down + } + case KEY_DOWN: { + + if (k.mod.shift) + break; + + bool found = selected_list.empty(); + + for (int i=0; iget_child_count(); i++) { + + HBoxContainer *hb = scroll_childs->get_child(i)->cast_to(); + if (!hb) continue; + + String current = hb->get_meta("name"); + + if (found) { + selected_list.clear(); + selected_list.insert(current, hb->get_meta("main_scene")); + + int last_y_visible = scroll->get_v_scroll() + scroll->get_size().y; + int offset_diff = (hb->get_pos().y + hb->get_size().y) - last_y_visible; + + if (offset_diff > 0) + scroll->set_v_scroll(scroll->get_v_scroll() + offset_diff); + + break; + + } else if (current==selected_list.back()->key()) { + + found = true; + } + } + + } break; + default: { + scancode_handled = false; + } break; + } + + if (scancode_handled) { + accept_event(); + + for(int i=0;iget_child_count();i++) { + CanvasItem *item = scroll_childs->get_child(i)->cast_to(); + if (item) + item->update(); + } + } + } +} + void ProjectManager::_favorite_pressed(Node *p_hb) { String clicked = p_hb->get_meta("name"); @@ -964,6 +1097,7 @@ void ProjectManager::_bind_methods() { ObjectTypeDB::bind_method("_load_recent_projects",&ProjectManager::_load_recent_projects); ObjectTypeDB::bind_method("_panel_draw",&ProjectManager::_panel_draw); ObjectTypeDB::bind_method("_panel_input",&ProjectManager::_panel_input); + ObjectTypeDB::bind_method("_unhandled_input",&ProjectManager::_unhandled_input); ObjectTypeDB::bind_method("_favorite_pressed",&ProjectManager::_favorite_pressed); ObjectTypeDB::bind_method("_install_project",&ProjectManager::_install_project); diff --git a/tools/editor/project_manager.h b/tools/editor/project_manager.h index 69467f50e72..74d1d3693cd 100644 --- a/tools/editor/project_manager.h +++ b/tools/editor/project_manager.h @@ -92,6 +92,7 @@ class ProjectManager : public Control { void _panel_draw(Node *p_hb); void _panel_input(const InputEvent& p_ev,Node *p_hb); + void _unhandled_input(const InputEvent& p_ev); void _favorite_pressed(Node *p_hb); protected: From 308d405c31f83ce538fea76d6e88931718afc012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= Date: Sun, 24 Jul 2016 00:02:19 +0200 Subject: [PATCH 14/63] Turn some prints to error logs, remove others Fixes #5876 in passing. --- core/io/image_loader.cpp | 3 +-- core/math/geometry.cpp | 14 +++++++------- core/object_type_db.cpp | 2 +- tools/editor/editor_file_system.cpp | 2 +- .../io_plugins/editor_mesh_import_plugin.cpp | 1 - 5 files changed, 10 insertions(+), 12 deletions(-) diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp index 05bad97e90e..ac6c00dc61d 100644 --- a/core/io/image_loader.cpp +++ b/core/io/image_loader.cpp @@ -51,7 +51,7 @@ Error ImageLoader::load_image(String p_file,Image *p_image, FileAccess *p_custom Error err; f=FileAccess::open(p_file,FileAccess::READ,&err); if (!f) { - print_line("ERROR OPENING FILE: "+p_file); + ERR_PRINTS("Error opening file: "+p_file); return err; } } @@ -76,7 +76,6 @@ Error ImageLoader::load_image(String p_file,Image *p_image, FileAccess *p_custom } - print_line("NO LOADER?"); if (!p_custom) memdelete(f); diff --git a/core/math/geometry.cpp b/core/math/geometry.cpp index 5b767212f56..790903eff50 100644 --- a/core/math/geometry.cpp +++ b/core/math/geometry.cpp @@ -629,7 +629,7 @@ DVector< Face3 > Geometry::wrap_geometry( DVector< Face3 > p_array,float *p_erro // create and initialize cells to zero - print_line("Wrapper: Initializing Cells"); + //print_line("Wrapper: Initializing Cells"); uint8_t ***cell_status=memnew_arr(uint8_t**,div_x); for(int i=0;i Geometry::wrap_geometry( DVector< Face3 > p_array,float *p_erro } // plot faces into cells - print_line("Wrapper (1/6): Plotting Faces"); + //print_line("Wrapper (1/6): Plotting Faces"); for (int i=0;i Geometry::wrap_geometry( DVector< Face3 > p_array,float *p_erro // determine which cells connect to the outside by traversing the outside and recursively flood-fill marking - print_line("Wrapper (2/6) Flood Filling"); + //print_line("Wrapper (2/6): Flood Filling"); for (int i=0;i Geometry::wrap_geometry( DVector< Face3 > p_array,float *p_erro // build faces for the inside-outside cell divisors - print_line("Wrapper (3/6): Building Faces"); + //print_line("Wrapper (3/6): Building Faces"); DVector wrapped_faces; @@ -709,7 +709,7 @@ DVector< Face3 > Geometry::wrap_geometry( DVector< Face3 > p_array,float *p_erro } } - print_line("Wrapper (4/6): Transforming Back Vertices"); + //print_line("Wrapper (4/6): Transforming Back Vertices"); // transform face vertices to global coords @@ -728,7 +728,7 @@ DVector< Face3 > Geometry::wrap_geometry( DVector< Face3 > p_array,float *p_erro } // clean up grid - print_line("Wrapper (5/6): Grid Cleanup"); + //print_line("Wrapper (5/6): Grid Cleanup"); for(int i=0;i Geometry::wrap_geometry( DVector< Face3 > p_array,float *p_erro if (p_error) *p_error=voxelsize.length(); - print_line("Wrapper (6/6): Finished."); + //print_line("Wrapper (6/6): Finished."); return wrapped_faces; } diff --git a/core/object_type_db.cpp b/core/object_type_db.cpp index 5f97df39a61..4998263961c 100644 --- a/core/object_type_db.cpp +++ b/core/object_type_db.cpp @@ -828,7 +828,7 @@ MethodBind* ObjectTypeDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind , c TypeInfo *type=types.getptr(instance_type); if (!type) { - print_line("couldn't bind method "+mdname+" for instance: "+instance_type); + ERR_PRINTS("Couldn't bind method '"+mdname+"' for instance: "+instance_type); memdelete(p_bind); ERR_FAIL_COND_V(!type,NULL); } diff --git a/tools/editor/editor_file_system.cpp b/tools/editor/editor_file_system.cpp index cb7cefea264..582b9e24904 100644 --- a/tools/editor/editor_file_system.cpp +++ b/tools/editor/editor_file_system.cpp @@ -657,7 +657,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir,DirAccess da->change_dir(".."); } } else { - ERR_PRINTS(TTR("Cannot go into subdir:")+" "+E->get()); + ERR_PRINTS("Cannot go into subdir: "+E->get()); } p_progress.update(idx,total); diff --git a/tools/editor/io_plugins/editor_mesh_import_plugin.cpp b/tools/editor/io_plugins/editor_mesh_import_plugin.cpp index 2c3ed2afd6a..da608292c18 100644 --- a/tools/editor/io_plugins/editor_mesh_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_mesh_import_plugin.cpp @@ -496,7 +496,6 @@ Error EditorMeshImportPlugin::import(const String& p_path, const Ref Date: Sat, 23 Jul 2016 23:59:24 +0200 Subject: [PATCH 15/63] Fix crash when GraphNode wasn't a child of a Control --- scene/gui/graph_node.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index 94001b2ac12..37055418651 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -559,7 +559,12 @@ Color GraphNode::get_connection_output_color(int p_idx) { void GraphNode::_input_event(const InputEvent& p_ev) { if (p_ev.type==InputEvent::MOUSE_BUTTON) { + + ERR_EXPLAIN("GraphNode must be the child of a GraphEdit node."); + ERR_FAIL_COND(get_parent_control() == NULL); + get_parent_control()->grab_focus(); + if(p_ev.mouse_button.pressed && p_ev.mouse_button.button_index==BUTTON_LEFT) { Vector2 mpos = Vector2(p_ev.mouse_button.x,p_ev.mouse_button.y); From ffdd9f16dd6a765c34f3a5d454419479fd431af6 Mon Sep 17 00:00:00 2001 From: Alex Piola Date: Sun, 24 Jul 2016 12:53:07 +0200 Subject: [PATCH 16/63] Fix for incorrect velocity report due to a typo. Closes #5854 --- servers/physics/body_pair_sw.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/servers/physics/body_pair_sw.cpp b/servers/physics/body_pair_sw.cpp index 3202e52abb0..43e52f26e89 100644 --- a/servers/physics/body_pair_sw.cpp +++ b/servers/physics/body_pair_sw.cpp @@ -323,13 +323,13 @@ bool BodyPairSW::setup(float p_step) { #endif if (A->can_report_contacts()) { - Vector3 crB = A->get_angular_velocity().cross( c.rA ) + A->get_linear_velocity(); - A->add_contact(global_A,-c.normal,depth,shape_A,global_B,shape_B,B->get_instance_id(),B->get_self(),crB); + Vector3 crA = A->get_angular_velocity().cross( c.rA ) + A->get_linear_velocity(); + A->add_contact(global_A,-c.normal,depth,shape_A,global_B,shape_B,B->get_instance_id(),B->get_self(),crA); } if (B->can_report_contacts()) { - Vector3 crA = A->get_angular_velocity().cross( c.rB ) + A->get_linear_velocity(); - B->add_contact(global_B,c.normal,depth,shape_B,global_A,shape_A,A->get_instance_id(),A->get_self(),crA); + Vector3 crB = B->get_angular_velocity().cross( c.rB ) + B->get_linear_velocity(); + B->add_contact(global_B,c.normal,depth,shape_B,global_A,shape_A,A->get_instance_id(),A->get_self(),crB); } if (A->is_shape_set_as_trigger(shape_A) || B->is_shape_set_as_trigger(shape_B) || (A->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC && B->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC)) { From 67640c84eb60238be7e75d1b0d9d937518f885fb Mon Sep 17 00:00:00 2001 From: Ignacio Etcheverry Date: Sat, 23 Jul 2016 21:25:00 +0200 Subject: [PATCH 17/63] Viewport: Replace obsolete "windows" group calls - Fixes neighbour focusing event propagation not being stopped --- scene/main/viewport.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index bdb2754e5e6..8faee0c5493 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -1782,7 +1782,6 @@ void Viewport::_gui_input_event(InputEvent p_event) { if (top->data.modal_exclusive || top->data.modal_frame==OS::get_singleton()->get_frames_drawn()) { //cancel event, sorry, modal exclusive EATS UP ALL //alternative, you can't pop out a window the same frame it was made modal (fixes many issues) - //get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID); get_tree()->set_input_as_handled(); return; // no one gets the event if exclusive NO ONE } @@ -2062,7 +2061,6 @@ void Viewport::_gui_input_event(InputEvent p_event) { - //get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID); get_tree()->set_input_as_handled(); @@ -2102,7 +2100,7 @@ void Viewport::_gui_input_event(InputEvent p_event) { if (gui.key_event_accepted) { - get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID); + get_tree()->set_input_as_handled(); break; } } @@ -2162,7 +2160,7 @@ void Viewport::_gui_input_event(InputEvent p_event) { if (next) { next->grab_focus(); - get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID); + get_tree()->set_input_as_handled(); } } @@ -2355,8 +2353,7 @@ void Viewport::_gui_control_grab_focus(Control* p_control) { if (gui.key_focus && gui.key_focus==p_control) return; - _gui_remove_focus(); - get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_gui_remove_focus"); + get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"_viewports","_gui_remove_focus"); gui.key_focus=p_control; p_control->notification(Control::NOTIFICATION_FOCUS_ENTER); p_control->update(); @@ -2664,6 +2661,7 @@ void Viewport::_bind_methods() { ObjectTypeDB::bind_method(_MD("is_input_disabled"), &Viewport::is_input_disabled); ObjectTypeDB::bind_method(_MD("_gui_show_tooltip"), &Viewport::_gui_show_tooltip); + ObjectTypeDB::bind_method(_MD("_gui_remove_focus"), &Viewport::_gui_remove_focus); ADD_PROPERTY( PropertyInfo(Variant::RECT2,"rect"), _SCS("set_rect"), _SCS("get_rect") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"own_world"), _SCS("set_use_own_world"), _SCS("is_using_own_world") ); From 7be70c5a3c4645e50f2287fcdc777a282153b3c0 Mon Sep 17 00:00:00 2001 From: George Marques Date: Sun, 24 Jul 2016 12:07:59 -0300 Subject: [PATCH 18/63] Avoid changing position when the window is fullscreen --- platform/windows/os_windows.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 6aee0d2399a..a3858fe641a 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -1476,6 +1476,7 @@ Point2 OS_Windows::get_window_position() const{ } void OS_Windows::set_window_position(const Point2& p_position){ + if (video_mode.fullscreen) return; RECT r; GetWindowRect(hWnd,&r); MoveWindow(hWnd,p_position.x,p_position.y,r.right-r.left,r.bottom-r.top,TRUE); From 60d937354790ac025ba0caef17a3ca7c81244492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= Date: Sun, 24 Jul 2016 17:11:32 +0200 Subject: [PATCH 19/63] Fix non-visible col number in text editor The issue itself cannot be fully fixed due to the changes in 864c0e8, but this solution makes the bug less likely to happen (it would only happen with > 5 digits for line or column, and/or a much bigger font. Could be further refined by taking the configured font into account... Fixed #5890. --- tools/editor/code_editor.cpp | 38 +++++++++++++++++++++++++++--------- tools/editor/code_editor.h | 3 ++- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/tools/editor/code_editor.cpp b/tools/editor/code_editor.cpp index 6c8d25aa01f..ed7a46d70d2 100644 --- a/tools/editor/code_editor.cpp +++ b/tools/editor/code_editor.cpp @@ -1032,8 +1032,8 @@ void CodeTextEditor::_reset_zoom() { void CodeTextEditor::_line_col_changed() { - String text = String()+TTR("Line:")+" "+itos(text_editor->cursor_get_line()+1)+", "+TTR("Col:")+" "+itos(text_editor->cursor_get_column()); - line_col->set_text(text); + line_nb->set_text(itos(text_editor->cursor_get_line() + 1)); + col_nb->set_text(itos(text_editor->cursor_get_column())); } void CodeTextEditor::_text_changed() { @@ -1191,6 +1191,7 @@ CodeTextEditor::CodeTextEditor() { HBoxContainer *status_bar = memnew( HBoxContainer ); status_mc->add_child(status_bar); status_bar->set_h_size_flags(SIZE_EXPAND_FILL); + status_bar->add_child( memnew( Label ) ); //to keep the height if the other labels are not visible idle = memnew( Timer ); add_child(idle); @@ -1212,14 +1213,33 @@ CodeTextEditor::CodeTextEditor() { status_bar->add_spacer(); - line_col = memnew( Label ); - status_bar->add_child(line_col); - line_col->set_valign(Label::VALIGN_CENTER); - line_col->set_autowrap(true); - line_col->set_v_size_flags(SIZE_FILL); - line_col->set_custom_minimum_size(Size2(100,1)*EDSCALE); - status_bar->add_child( memnew( Label ) ); //to keep the height if the other labels are not visible + Label *line_txt = memnew( Label ); + status_bar->add_child(line_txt); + line_txt->set_align(Label::ALIGN_RIGHT); + line_txt->set_valign(Label::VALIGN_CENTER); + line_txt->set_v_size_flags(SIZE_FILL); + line_txt->set_text(TTR("Line:")); + line_nb = memnew( Label ); + status_bar->add_child(line_nb); + line_nb->set_valign(Label::VALIGN_CENTER); + line_nb->set_v_size_flags(SIZE_FILL); + line_nb->set_autowrap(true); // workaround to prevent resizing the label on each change + line_nb->set_custom_minimum_size(Size2(40,1)*EDSCALE); + + Label *col_txt = memnew( Label ); + status_bar->add_child(col_txt); + col_txt->set_align(Label::ALIGN_RIGHT); + col_txt->set_valign(Label::VALIGN_CENTER); + col_txt->set_v_size_flags(SIZE_FILL); + col_txt->set_text(TTR("Col:")); + + col_nb = memnew( Label ); + status_bar->add_child(col_nb); + col_nb->set_valign(Label::VALIGN_CENTER); + col_nb->set_v_size_flags(SIZE_FILL); + col_nb->set_autowrap(true); // workaround to prevent resizing the label on each change + col_nb->set_custom_minimum_size(Size2(40,1)*EDSCALE); text_editor->connect("input_event", this,"_text_editor_input_event"); text_editor->connect("cursor_changed", this,"_line_col_changed"); diff --git a/tools/editor/code_editor.h b/tools/editor/code_editor.h index 7983c46f7af..88d882bd337 100644 --- a/tools/editor/code_editor.h +++ b/tools/editor/code_editor.h @@ -196,7 +196,8 @@ class CodeTextEditor : public VBoxContainer { TextEdit *text_editor; FindReplaceBar *find_replace_bar; - Label *line_col; + Label *line_nb; + Label *col_nb; Label *info; Timer *idle; Timer *code_complete_timer; From 991d9394d7a3ff03b412e80c8579523b3b4d47fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= Date: Sun, 24 Jul 2016 18:17:20 +0200 Subject: [PATCH 20/63] Bump version to 2.1-rc1 --- version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.py b/version.py index dd80ca1b19a..19ff05f7152 100644 --- a/version.py +++ b/version.py @@ -2,4 +2,4 @@ short_name="godot" name="Godot Engine" major=2 minor=1 -status="beta" +status="rc1" From 85f365bbffc0735a82d29ddce4e7991814ae1a5b Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sun, 24 Jul 2016 14:37:26 -0300 Subject: [PATCH 21/63] shows progress (bytes) on download even if getting chunked content --- tools/editor/asset_library_editor_plugin.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/editor/asset_library_editor_plugin.cpp b/tools/editor/asset_library_editor_plugin.cpp index 4f685badfb8..b6040b89282 100644 --- a/tools/editor/asset_library_editor_plugin.cpp +++ b/tools/editor/asset_library_editor_plugin.cpp @@ -325,6 +325,7 @@ void EditorAssetLibraryItemDownload::_http_download_completed(int p_status, int String error_text; + print_line("COMPLETED: "+itos(p_status)+" code: "+itos(p_code)+" data size: "+itos(p_data.size())); switch(p_status) { @@ -383,7 +384,9 @@ void EditorAssetLibraryItemDownload::_http_download_completed(int p_status, int print_line("max: "+itos(download->get_body_size())+" bytes: "+itos(download->get_downloaded_bytes())); install->set_disabled(false); - status->set_text("Success!"); + progress->set_val(download->get_downloaded_bytes()); + + status->set_text("Success! ("+String::humanize_size(download->get_downloaded_bytes())+")"); set_process(false); } @@ -411,6 +414,10 @@ void EditorAssetLibraryItemDownload::_notification(int p_what) { progress->set_val(download->get_downloaded_bytes()); int cstatus = download->get_http_client_status(); + + if (cstatus==HTTPClient::STATUS_BODY) + status->set_text("Fetching: "+String::humanize_size(download->get_downloaded_bytes())); + if (cstatus!=prev_status) { switch(cstatus) { @@ -423,9 +430,6 @@ void EditorAssetLibraryItemDownload::_notification(int p_what) { case HTTPClient::STATUS_REQUESTING: { status->set_text("Requesting.."); } break; - case HTTPClient::STATUS_BODY: { - status->set_text("Downloading.."); - } break; default: {} } prev_status=cstatus; From ab93fd1af9db397f54cc0103867aa9953572fb84 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sun, 24 Jul 2016 16:09:43 -0300 Subject: [PATCH 22/63] Add thread support to HTTPRequest, changed assetlib to use it. --- scene/main/http_request.cpp | 108 +++++++++++++++---- scene/main/http_request.h | 13 ++- tools/editor/asset_library_editor_plugin.cpp | 7 +- 3 files changed, 102 insertions(+), 26 deletions(-) diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index 040d509286e..9b79af32bf8 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -105,6 +105,9 @@ Error HTTPRequest::request(const String& p_url, const Vector& p_custom_h } Error err = _parse_url(p_url); + if (err) + return err; + validate_ssl=p_ssl_validate_domain; bool has_user_agent=false; @@ -127,19 +130,52 @@ Error HTTPRequest::request(const String& p_url, const Vector& p_custom_h headers.push_back("Accept: */*"); } + requesting=true; - err = _request(); + if (use_threads) { + + thread_done=false; + thread_request_quit=false; + client->set_blocking_mode(true); + thread=Thread::create(_thread_func,this); + } else { + client->set_blocking_mode(false); + err = _request(); + if (err!=OK) { + call_deferred("_request_done",RESULT_CANT_CONNECT,0,StringArray(),ByteArray()); + return ERR_CANT_CONNECT; + } - if (err==OK) { set_process(true); - requesting=true; + } - return err; + return OK; } +void HTTPRequest::_thread_func(void *p_userdata) { + + HTTPRequest *hr = (HTTPRequest*)p_userdata; + + Error err = hr->_request(); + + if (err!=OK) { + hr->call_deferred("_request_done",RESULT_CANT_CONNECT,0,StringArray(),ByteArray()); + } else { + while(!hr->thread_request_quit) { + + bool exit = hr->_update_connection(); + if (exit) + break; + OS::get_singleton()->delay_usec(1); + } + } + + hr->thread_done=true; +} + void HTTPRequest::cancel_request() { if (!requesting) @@ -147,6 +183,11 @@ void HTTPRequest::cancel_request() { if (!use_threads) { set_process(false); + } else { + thread_request_quit=true; + Thread::wait_to_finish(thread); + memdelete(thread); + thread=NULL; } if (file) { @@ -167,7 +208,7 @@ void HTTPRequest::cancel_request() { bool HTTPRequest::_handle_response(bool *ret_value) { if (!client->has_response()) { - call_deferred("emit_signal","request_completed",RESULT_NO_RESPONSE,0,StringArray(),ByteArray()); + call_deferred("_request_done",RESULT_NO_RESPONSE,0,StringArray(),ByteArray()); *ret_value=true; return true; } @@ -187,7 +228,7 @@ bool HTTPRequest::_handle_response(bool *ret_value) { //redirect if (max_redirects>=0 && redirections>=max_redirects) { - call_deferred("emit_signal","request_completed",RESULT_REDIRECT_LIMIT_REACHED,response_code,response_headers,ByteArray()); + call_deferred("_request_done",RESULT_REDIRECT_LIMIT_REACHED,response_code,response_headers,ByteArray()); *ret_value=true; return true; } @@ -239,7 +280,8 @@ bool HTTPRequest::_update_connection() { switch( client->get_status() ) { case HTTPClient::STATUS_DISCONNECTED: { - return true; //end it, since it's doing something + call_deferred("_request_done",RESULT_CANT_CONNECT,0,StringArray(),ByteArray()); + return true; //end it, since it's doing something } break; case HTTPClient::STATUS_RESOLVING: { client->poll(); @@ -247,7 +289,7 @@ bool HTTPRequest::_update_connection() { return false; } break; case HTTPClient::STATUS_CANT_RESOLVE: { - call_deferred("emit_signal","request_completed",RESULT_CANT_RESOLVE,0,StringArray(),ByteArray()); + call_deferred("_request_done",RESULT_CANT_RESOLVE,0,StringArray(),ByteArray()); return true; } break; @@ -258,7 +300,7 @@ bool HTTPRequest::_update_connection() { } break; //connecting to ip case HTTPClient::STATUS_CANT_CONNECT: { - call_deferred("emit_signal","request_completed",RESULT_CANT_CONNECT,0,StringArray(),ByteArray()); + call_deferred("_request_done",RESULT_CANT_CONNECT,0,StringArray(),ByteArray()); return true; } break; @@ -276,17 +318,17 @@ bool HTTPRequest::_update_connection() { return ret_value; - call_deferred("emit_signal","request_completed",RESULT_SUCCESS,response_code,response_headers,ByteArray()); + call_deferred("_request_done",RESULT_SUCCESS,response_code,response_headers,ByteArray()); return true; } if (got_response && body_len<0) { //chunked transfer is done - call_deferred("emit_signal","request_completed",RESULT_SUCCESS,response_code,response_headers,body); + call_deferred("_request_done",RESULT_SUCCESS,response_code,response_headers,body); return true; } - call_deferred("emit_signal","request_completed",RESULT_CHUNKED_BODY_SIZE_MISMATCH,response_code,response_headers,ByteArray()); + call_deferred("_request_done",RESULT_CHUNKED_BODY_SIZE_MISMATCH,response_code,response_headers,ByteArray()); return true; //request migh have been done } else { @@ -294,7 +336,7 @@ bool HTTPRequest::_update_connection() { Error err = client->request(HTTPClient::METHOD_GET,request_string,headers); if (err!=OK) { - call_deferred("emit_signal","request_completed",RESULT_CONNECTION_ERROR,0,StringArray(),ByteArray()); + call_deferred("_request_done",RESULT_CONNECTION_ERROR,0,StringArray(),ByteArray()); return true; } @@ -320,7 +362,7 @@ bool HTTPRequest::_update_connection() { if (!client->is_response_chunked() && client->get_response_body_length()==0) { - call_deferred("emit_signal","request_completed",RESULT_SUCCESS,response_code,response_headers,ByteArray()); + call_deferred("_request_done",RESULT_SUCCESS,response_code,response_headers,ByteArray()); return true; } @@ -331,7 +373,7 @@ bool HTTPRequest::_update_connection() { body_len=client->get_response_body_length(); if (body_size_limit>=0 && body_len>body_size_limit) { - call_deferred("emit_signal","request_completed",RESULT_BODY_SIZE_LIMIT_EXCEEDED,response_code,response_headers,ByteArray()); + call_deferred("_request_done",RESULT_BODY_SIZE_LIMIT_EXCEEDED,response_code,response_headers,ByteArray()); return true; } } @@ -340,7 +382,8 @@ bool HTTPRequest::_update_connection() { 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()); + call_deferred("_request_done",RESULT_DOWNLOAD_FILE_CANT_OPEN,response_code,response_headers,ByteArray()); + return true; } } } @@ -356,7 +399,7 @@ bool HTTPRequest::_update_connection() { 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()); + call_deferred("_request_done",RESULT_DOWNLOAD_FILE_WRITE_ERROR,response_code,response_headers,ByteArray()); return true; } } else { @@ -364,18 +407,18 @@ bool HTTPRequest::_update_connection() { } 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()); + call_deferred("_request_done",RESULT_BODY_SIZE_LIMIT_EXCEEDED,response_code,response_headers,ByteArray()); return true; } if (body_len>=0) { if (downloaded==body_len) { - call_deferred("emit_signal","request_completed",RESULT_SUCCESS,response_code,response_headers,body); + call_deferred("_request_done",RESULT_SUCCESS,response_code,response_headers,body); return true; } /*if (body.size()>=body_len) { - call_deferred("emit_signal","request_completed",RESULT_BODY_SIZE_MISMATCH,response_code,response_headers,ByteArray()); + call_deferred("_request_done",RESULT_BODY_SIZE_MISMATCH,response_code,response_headers,ByteArray()); return true; }*/ } @@ -384,11 +427,11 @@ bool HTTPRequest::_update_connection() { } break; // request resulted in body: { } break which must be read case HTTPClient::STATUS_CONNECTION_ERROR: { - call_deferred("emit_signal","request_completed",RESULT_CONNECTION_ERROR,0,StringArray(),ByteArray()); + call_deferred("_request_done",RESULT_CONNECTION_ERROR,0,StringArray(),ByteArray()); return true; } break; case HTTPClient::STATUS_SSL_HANDSHAKE_ERROR: { - call_deferred("emit_signal","request_completed",RESULT_SSL_HANDSHAKE_ERROR,0,StringArray(),ByteArray()); + call_deferred("_request_done",RESULT_SSL_HANDSHAKE_ERROR,0,StringArray(),ByteArray()); return true; } break; @@ -397,17 +440,35 @@ bool HTTPRequest::_update_connection() { ERR_FAIL_V(false); } + +void HTTPRequest::_request_done(int p_status, int p_code, const StringArray& headers, const ByteArray& p_data) { + + + cancel_request(); + emit_signal("request_completed",p_status,p_code,headers,p_data); +} + + void HTTPRequest::_notification(int p_what) { if (p_what==NOTIFICATION_PROCESS) { + if (use_threads) + return; bool done = _update_connection(); if (done) { set_process(false); + //cancel_request(); called from _request done now + } + } + + if (p_what==NOTIFICATION_EXIT_TREE) { + if (requesting) { cancel_request(); } } + } void HTTPRequest::set_use_threads(bool p_use) { @@ -491,6 +552,7 @@ void HTTPRequest::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_body_size"),&HTTPRequest::get_body_size); ObjectTypeDB::bind_method(_MD("_redirect_request"),&HTTPRequest::_redirect_request); + ObjectTypeDB::bind_method(_MD("_request_done"),&HTTPRequest::_request_done); ADD_PROPERTY(PropertyInfo(Variant::BOOL,"use_threads"),_SCS("set_use_threads"),_SCS("is_using_threads")); ADD_PROPERTY(PropertyInfo(Variant::INT,"body_size_limit",PROPERTY_HINT_RANGE,"-1,2000000000"),_SCS("set_body_size_limit"),_SCS("get_body_size_limit")); @@ -517,6 +579,7 @@ void HTTPRequest::_bind_methods() { HTTPRequest::HTTPRequest() { + thread=NULL; port=80; redirections=0; @@ -530,6 +593,7 @@ HTTPRequest::HTTPRequest() requesting=false; client.instance(); use_threads=false; + thread_done=false; body_size_limit=-1; file=NULL; status=HTTPClient::STATUS_DISCONNECTED; diff --git a/scene/main/http_request.h b/scene/main/http_request.h index 7c3ccb2eb92..8dd433982bc 100644 --- a/scene/main/http_request.h +++ b/scene/main/http_request.h @@ -32,6 +32,7 @@ #include "node.h" #include "io/http_client.h" #include "os/file_access.h" +#include "os/thread.h" class HTTPRequest : public Node { @@ -69,7 +70,7 @@ private: bool request_sent; Ref client; ByteArray body; - bool use_threads; + volatile bool use_threads; bool got_response; int response_code; @@ -80,7 +81,7 @@ private: FileAccess *file; int body_len; - int downloaded; + volatile int downloaded; int body_size_limit; int redirections; @@ -93,11 +94,19 @@ private: void _redirect_request(const String& p_new_url); + bool _handle_response(bool *ret_value); Error _parse_url(const String& p_url); Error _request(); + volatile bool thread_done; + volatile bool thread_request_quit; + + Thread *thread; + + void _request_done(int p_status, int p_code, const StringArray& headers, const ByteArray& p_data); + static void _thread_func(void *p_userdata); protected: diff --git a/tools/editor/asset_library_editor_plugin.cpp b/tools/editor/asset_library_editor_plugin.cpp index b6040b89282..3fd5d2b5d1a 100644 --- a/tools/editor/asset_library_editor_plugin.cpp +++ b/tools/editor/asset_library_editor_plugin.cpp @@ -134,13 +134,13 @@ EditorAssetLibraryItem::EditorAssetLibraryItem() { category = memnew( LinkButton ); category->set_text("Editor Tools"); category->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER); - title->connect("pressed",this,"_category_clicked"); + category->connect("pressed",this,"_category_clicked"); vb->add_child(category); author = memnew( LinkButton ); author->set_text("Johny Tolengo"); author->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER); - title->connect("pressed",this,"_author_clicked"); + author->connect("pressed",this,"_author_clicked"); vb->add_child(author); HBoxContainer *rating_hb = memnew( HBoxContainer ); @@ -461,6 +461,7 @@ void EditorAssetLibraryItemDownload::_install() { void EditorAssetLibraryItemDownload::_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"); @@ -1011,6 +1012,7 @@ void EditorAssetLibrary::_api_request(const String& p_request, RequestType p_req if (requesting!=REQUESTING_NONE) { request->cancel_request(); } + requesting=p_request_type; error_hb->hide(); @@ -1469,6 +1471,7 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { request = memnew( HTTPRequest ); add_child(request); + request->set_use_threads(EDITOR_DEF("asset_library/use_threads",true)); request->connect("request_completed",this,"_http_request_completed"); last_queue_id=0; From ed094d52a9a281fc0735f633b02adc7f2cf11cf8 Mon Sep 17 00:00:00 2001 From: MarianoGNU Date: Sun, 24 Jul 2016 16:16:02 -0300 Subject: [PATCH 23/63] expose bottom panel button to EditorPlugin scripts --- tools/editor/editor_plugin.cpp | 4 ++-- tools/editor/editor_plugin.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/editor/editor_plugin.cpp b/tools/editor/editor_plugin.cpp index 01e6b613c00..2bdd4caebe2 100644 --- a/tools/editor/editor_plugin.cpp +++ b/tools/editor/editor_plugin.cpp @@ -44,9 +44,9 @@ void EditorPlugin::remove_custom_type(const String& p_type){ } -void EditorPlugin::add_control_to_bottom_panel(Control *p_control, const String &p_title) { +ToolButton * EditorPlugin::add_control_to_bottom_panel(Control *p_control, const String &p_title) { - EditorNode::get_singleton()->add_bottom_panel_item(p_title,p_control); + return EditorNode::get_singleton()->add_bottom_panel_item(p_title,p_control); } void EditorPlugin::add_control_to_dock(DockSlot p_slot,Control *p_control) { diff --git a/tools/editor/editor_plugin.h b/tools/editor/editor_plugin.h index b93b6624d05..b960a7d5afc 100644 --- a/tools/editor/editor_plugin.h +++ b/tools/editor/editor_plugin.h @@ -29,6 +29,7 @@ #ifndef EDITOR_PLUGIN_H #define EDITOR_PLUGIN_H +#include "scene/gui/tool_button.h" #include "scene/main/node.h" #include "scene/resources/texture.h" #include "undo_redo.h" @@ -92,7 +93,7 @@ public: //TODO: send a resoucre for editing to the editor node? void add_control_to_container(CustomControlContainer p_location, Control *p_control); - void add_control_to_bottom_panel(Control *p_control, const String &p_title); + ToolButton *add_control_to_bottom_panel(Control *p_control, const String &p_title); void add_control_to_dock(DockSlot p_slot,Control *p_control); void remove_control_from_docks(Control *p_control); void remove_control_from_bottom_panel(Control *p_control); From 23a20791d1f0c0760c0e22d51c0450b58b0e05f1 Mon Sep 17 00:00:00 2001 From: MarianoGNU Date: Sun, 24 Jul 2016 18:05:05 -0300 Subject: [PATCH 24/63] Update documentation. --- doc/base/classes.xml | 2 +- tools/editor/editor_plugin.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/base/classes.xml b/doc/base/classes.xml index 4c2a0fe7ba6..d70b11b5ae8 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -11281,7 +11281,7 @@ - Add a control to the bottom panel (together with Output, Debug, Animation, etc). If your plugin is being removed, also make sure to remove your control by calling [method remove_control_from_bottom_panel]. + Add a control to the bottom panel (together with Output, Debug, Animation, etc). Returns a reference to the button added. It's up to you to hide/show the button when needed. If your plugin is being removed, also make sure to remove your control by calling [method remove_control_from_bottom_panel]. diff --git a/tools/editor/editor_plugin.cpp b/tools/editor/editor_plugin.cpp index 2bdd4caebe2..0d162cbe567 100644 --- a/tools/editor/editor_plugin.cpp +++ b/tools/editor/editor_plugin.cpp @@ -284,7 +284,7 @@ Control *EditorPlugin::get_base_control() { void EditorPlugin::_bind_methods() { ObjectTypeDB::bind_method(_MD("add_control_to_container","container","control:Control"),&EditorPlugin::add_control_to_container); - ObjectTypeDB::bind_method(_MD("add_control_to_bottom_panel","control:Control","title"),&EditorPlugin::add_control_to_bottom_panel); + ObjectTypeDB::bind_method(_MD("add_control_to_bottom_panel:ToolButton","control:Control","title"),&EditorPlugin::add_control_to_bottom_panel); ObjectTypeDB::bind_method(_MD("add_control_to_dock","slot","control:Control"),&EditorPlugin::add_control_to_dock); ObjectTypeDB::bind_method(_MD("remove_control_from_docks","control:Control"),&EditorPlugin::remove_control_from_docks); ObjectTypeDB::bind_method(_MD("remove_control_from_bottom_panel","control:Control"),&EditorPlugin::remove_control_from_bottom_panel); From 7dbdfe8dbd761631850db2e3476b74ae082fbe14 Mon Sep 17 00:00:00 2001 From: Bojidar Marinov Date: Mon, 25 Jul 2016 12:07:02 +0300 Subject: [PATCH 25/63] Fix default ranges of the inspector Probably closes #3091 (Should apply to Variant::REAL and Variant::INT) --- tools/editor/property_editor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp index 54d197f10d6..26a49e92f07 100644 --- a/tools/editor/property_editor.cpp +++ b/tools/editor/property_editor.cpp @@ -3039,10 +3039,10 @@ void PropertyEditor::update_tree() { } else { if (p.type == Variant::REAL) { - item->set_range_config(1, -65536, 65535, 0.001); + item->set_range_config(1, -16777216, 16777216, 0.001); } else { - item->set_range_config(1, -65536, 65535, 1); + item->set_range_config(1, -2147483647, 2147483647, 1); } }; From a2b8ef6d5108f1822f323e23e8546878e3ec8fe3 Mon Sep 17 00:00:00 2001 From: Johan Manuel Date: Mon, 25 Jul 2016 15:31:57 +0200 Subject: [PATCH 26/63] Fix some warnings --- servers/audio/audio_mixer_sw.h | 3 +-- servers/audio_server.h | 3 ++- tools/editor/editor_node.cpp | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/servers/audio/audio_mixer_sw.h b/servers/audio/audio_mixer_sw.h index 950ed19af6d..e924b518cc8 100644 --- a/servers/audio/audio_mixer_sw.h +++ b/servers/audio/audio_mixer_sw.h @@ -69,8 +69,7 @@ private: MIX_VOLRAMP_FRAC_MASK=MIX_VOLRAMP_FRAC_LEN-1, MIX_FILTER_FRAC_BITS=16, MIX_FILTER_RAMP_FRAC_BITS=8, - MIX_VOL_MOVE_TO_24=4, - MAX_REVERBS=4 + MIX_VOL_MOVE_TO_24=4 }; diff --git a/servers/audio_server.h b/servers/audio_server.h index 50194af4a53..9e21e6b1839 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -65,7 +65,8 @@ public: REVERB_SMALL, REVERB_MEDIUM, REVERB_LARGE, - REVERB_HALL + REVERB_HALL, + MAX_REVERBS }; virtual ChannelID channel_alloc(RID p_sample)=0; diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 30b89cacc5a..2839708f8da 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -1213,7 +1213,7 @@ void EditorNode::_dialog_action(String p_file) { case FILE_SAVE_SCENE: case FILE_SAVE_AS_SCENE: { - if (file->get_mode()==FileDialog::MODE_SAVE_FILE) { + if (file->get_mode()==EditorFileDialog::MODE_SAVE_FILE) { //_save_scene(p_file); _save_scene_with_preview(p_file); @@ -1223,7 +1223,7 @@ void EditorNode::_dialog_action(String p_file) { } break; case FILE_SAVE_AND_RUN: { - if (file->get_mode()==FileDialog::MODE_SAVE_FILE) { + if (file->get_mode()==EditorFileDialog::MODE_SAVE_FILE) { //_save_scene(p_file); _save_scene_with_preview(p_file); @@ -1448,7 +1448,7 @@ void EditorNode::_dialog_action(String p_file) { } break; default: { //save scene? - if (file->get_mode()==FileDialog::MODE_SAVE_FILE) { + if (file->get_mode()==EditorFileDialog::MODE_SAVE_FILE) { //_save_scene(p_file); _save_scene_with_preview(p_file); From 2f8910185ea42a4b401a98b04f869562c87ffed6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20L=C3=B3pez=20=C3=9Abeda?= Date: Mon, 25 Jul 2016 21:15:27 +0200 Subject: [PATCH 27/63] Update Tween class documentation --- doc/base/classes.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/base/classes.xml b/doc/base/classes.xml index d70b11b5ae8..d741dbbb656 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -12264,7 +12264,7 @@ file.open("user://save_game.dat", file.WRITE) file.store_string(content) file.close() - + func load(): var file = File.new() file.open("user://save_game.dat", file.READ) @@ -15692,7 +15692,7 @@ - ImmediateGeometry is a node used for displaying simple geometry created from code, very similar to how glBegin() and glEnd() worked in old versions of OpenGL (1.x). + ImmediateGeometry is a node used for displaying simple geometry created from code, very similar to how glBegin() and glEnd() worked in old versions of OpenGL (1.x). Simply call [method begin()], and add vertices. For custom vertex colors, uvs, normal, etc. call one of the set_ functions below before adding each vertex. When done, call [method end] Calls to begin/end are accumulative and all geometry is added together. To clear all the geometry, call [method clear]. If a material override is set, and this material contains a texture, it's possible to override the texture used in this material for every begin/end set of calls. @@ -42401,7 +42401,7 @@ Because it is easy to get it wrong, here is a quick usage example: [codeblock] var tween = get_node("Tween") - tween.interpolate_property(get_node("Node2D_to_move"), "transform/pos", Vector2(0,0), Vector2(100,100), Tween.TRANS_LINEAR, Tween.EASE_IN_OUT) + tween.interpolate_property(get_node("Node2D_to_move"), "transform/pos", Vector2(0,0), Vector2(100,100), 1, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT) tween.start() [/codeblock] Some of the methods of this class require a property name. You can get the property name by hovering over the property in the inspector of the editor. From a155342eca0bf4417838e9d4f081450014f47e11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= Date: Mon, 25 Jul 2016 23:08:46 +0200 Subject: [PATCH 28/63] GLES2: Check for GPU capabilities to display an error The engine will still segfault, but the error message should be displayed by the OS in a blocking manner, so that it will only crash once users have acknowledged the error dialog. Closes #1162. --- drivers/gles2/rasterizer_gles2.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index 4cd97a7f6a8..ba93a26a2d0 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -10788,8 +10788,17 @@ void RasterizerGLES2::init() { if (OS::get_singleton()->is_stdout_verbose()) { print_line(String("GLES2: Using GLEW ") + (const char*) glewGetString(GLEW_VERSION)); } -#endif + // Check for GL 2.1 compatibility, if not bail out + if (!glewIsSupported("GL_VERSION_2_1")) { + ERR_PRINT("Your system's graphic drivers seem not to support OpenGL 2.1 / GLES 2.0, sorry :(\n" + "Try a drivers update, buy a new GPU or try software rendering on Linux; Godot will now crash with a segmentation fault."); + OS::get_singleton()->alert("Your system's graphic drivers seem not to support OpenGL 2.1 / GLES 2.0, sorry :(\n" + "Godot Engine will self-destruct as soon as you acknowledge this error message.", + "Fatal error: Insufficient OpenGL / GLES drivers"); + // TODO: If it's even possible, we should stop the execution without segfault and memory leaks :) + } +#endif From 213a57ccafdf2f4fcc472801c60332d40cfe6464 Mon Sep 17 00:00:00 2001 From: "Daniel J. Ramirez" Date: Mon, 25 Jul 2016 21:45:20 -0500 Subject: [PATCH 29/63] Stop baking process if there is no geometry in the BakedLightInstance. moved missing baked light warning to BakedLightInstance configuration warning --- scene/3d/baked_light_instance.cpp | 10 ++++++++++ scene/3d/baked_light_instance.h | 2 ++ tools/editor/plugins/baked_light_baker.cpp | 4 ++++ tools/editor/plugins/baked_light_editor_plugin.cpp | 6 ++++-- 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/scene/3d/baked_light_instance.cpp b/scene/3d/baked_light_instance.cpp index fafa62866f2..ca3a309568e 100644 --- a/scene/3d/baked_light_instance.cpp +++ b/scene/3d/baked_light_instance.cpp @@ -60,6 +60,8 @@ void BakedLightInstance::set_baked_light(const Ref& p_baked_light) { // VS::get_singleton()->instance_geometry_set_baked_light(E->get()->get_instance(),baked_light.is_valid()?get_instance():RID()); // } } + + update_configuration_warning(); } Ref BakedLightInstance::get_baked_light() const{ @@ -77,6 +79,14 @@ DVector BakedLightInstance::get_faces(uint32_t p_usage_flags) const { } +String BakedLightInstance::get_configuration_warning() const { + if (get_baked_light().is_null()) { + return TTR("BakedLightInstance does not contain a BakedLight resource."); + } + return String(); +} + + void BakedLightInstance::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_baked_light","baked_light"),&BakedLightInstance::set_baked_light); diff --git a/scene/3d/baked_light_instance.h b/scene/3d/baked_light_instance.h index 92c2d509865..002e55df1d8 100644 --- a/scene/3d/baked_light_instance.h +++ b/scene/3d/baked_light_instance.h @@ -55,6 +55,8 @@ public: virtual AABB get_aabb() const; virtual DVector get_faces(uint32_t p_usage_flags) const; + String get_configuration_warning() const; + BakedLightInstance(); }; diff --git a/tools/editor/plugins/baked_light_baker.cpp b/tools/editor/plugins/baked_light_baker.cpp index 6a88ba4cbe8..a2e94e88550 100644 --- a/tools/editor/plugins/baked_light_baker.cpp +++ b/tools/editor/plugins/baked_light_baker.cpp @@ -1772,6 +1772,10 @@ void BakedLightBaker::bake(const Ref &p_light, Node* p_node) { mat_map.clear(); tex_map.clear(); print_line("\ttotal triangles: "+itos(triangles.size())); + // no geometry + if (triangles.size() == 0) { + return; + } ep.step(TTR("Fixing Lights"),1); _fix_lights(); ep.step(TTR("Making BVH"),2); diff --git a/tools/editor/plugins/baked_light_editor_plugin.cpp b/tools/editor/plugins/baked_light_editor_plugin.cpp index df76f28ae05..a58a0c25e23 100644 --- a/tools/editor/plugins/baked_light_editor_plugin.cpp +++ b/tools/editor/plugins/baked_light_editor_plugin.cpp @@ -206,8 +206,9 @@ void BakedLightEditor::_menu_option(int p_option) { void BakedLightEditor::_bake_pressed() { ERR_FAIL_COND(!node); - if (node->get_baked_light().is_null()) { - err_dialog->set_text(TTR("BakedLightInstance does not contain a BakedLight resource.")); + const String conf_warning = node->get_configuration_warning(); + if (!conf_warning.empty()) { + err_dialog->set_text(conf_warning); err_dialog->popup_centered_minsize(); button_bake->set_pressed(false); return; @@ -236,6 +237,7 @@ void BakedLightEditor::_bake_pressed() { update_timeout=0; last_rays_time=0; + button_bake->set_pressed(false); set_process(true); } From ccf6b3151d1445f3e1bc351056a64b8f0094bc63 Mon Sep 17 00:00:00 2001 From: Andreas Haas Date: Tue, 26 Jul 2016 11:54:59 +0200 Subject: [PATCH 30/63] Add gamepad mapping for the steam controller userspace driver. --- main/input_default.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/main/input_default.cpp b/main/input_default.cpp index 5e66a8b5851..618d0d4f7d2 100644 --- a/main/input_default.cpp +++ b/main/input_default.cpp @@ -588,6 +588,7 @@ static const char *s_ControllerMappings [] = "030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5,", "030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,", + "030000005e0400008e02000001000000,Microsoft X-Box 360 pad,leftx:a0,lefty:a1,dpdown:h0.1,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:h0.2,lefttrigger:a2,x:b2,dpup:h0.4,back:b6,leftshoulder:b4,y:b3,a:b0,dpright:h0.8,righttrigger:a5,b:b1,", "030000005e0400008e02000004010000,Microsoft X-Box 360 pad,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,guide:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,", "030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", From fd659e869b86bc72d1e22ee601ba46d145b8dbaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= Date: Tue, 26 Jul 2016 15:16:45 +0200 Subject: [PATCH 31/63] Windows: Make alert message box use MB_TASKMODAL This flag pauses the current running thread, allowing for the user to see the alert and acknowledge it before the thread continues (and e.g. crashes :)). Thanks to @SuperUserNameMan for finding it. Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/ms645505(v=vs.85).aspx --- platform/windows/os_windows.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index a3858fe641a..571277f91ea 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -1343,7 +1343,7 @@ void OS_Windows::vprint(const char* p_format, va_list p_list, bool p_stderr) { void OS_Windows::alert(const String& p_alert,const String& p_title) { if (!is_no_window_mode_enabled()) - MessageBoxW(NULL,p_alert.c_str(),p_title.c_str(),MB_OK|MB_ICONEXCLAMATION); + MessageBoxW(NULL, p_alert.c_str(), p_title.c_str(), MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL); else print_line("ALERT: "+p_alert); } From 9151eb591dcab408d3a7e4d9e3b3874c2e281acf Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Tue, 26 Jul 2016 17:24:34 -0300 Subject: [PATCH 32/63] Changed the way the step decimals are computed to a safer way, fixes many issues. --- bin/tests/test_math.cpp | 1 + core/math/math_funcs.cpp | 34 +++++++++++++++++-------------- core/math/math_funcs.h | 2 +- modules/gdscript/gd_functions.cpp | 2 +- scene/gui/spin_box.cpp | 2 +- scene/gui/tree.cpp | 8 ++++---- 6 files changed, 27 insertions(+), 22 deletions(-) diff --git a/bin/tests/test_math.cpp b/bin/tests/test_math.cpp index 8e08969fa4c..4b686e8af88 100644 --- a/bin/tests/test_math.cpp +++ b/bin/tests/test_math.cpp @@ -113,6 +113,7 @@ uint32_t ihash3( uint32_t a) MainLoop* test() { + print_line(itos(Math::step_decimals( 0.0001 ))); return NULL; { diff --git a/core/math/math_funcs.cpp b/core/math/math_funcs.cpp index 0fbd0312142..64615fe6b4d 100644 --- a/core/math/math_funcs.cpp +++ b/core/math/math_funcs.cpp @@ -206,25 +206,29 @@ double Math::ceil(double p_x) { return ::ceil(p_x); } -int Math::decimals(double p_step) { +int Math::step_decimals(double p_step) { - int max=4; - double llimit = Math::pow(0.1,max); - double ulimit = 1.0-llimit; - int i=0; - while( max) { + static const int maxn=9; + static const double sd[maxn]={ + 0.9999, // somehow compensate for floating point error + 0.09999, + 0.009999, + 0.0009999, + 0.00009999, + 0.000009999, + 0.0000009999, + 0.00000009999, + 0.000000009999 + }; - float d = absf(p_step) - Math::floor(absf(p_step)); - - if (dulimit) - break; - p_step*=10.0; - max--; - i++; + double as=absf(p_step); + for(int i=0;i=sd[i]) { + return i; + } } - return i; - + return maxn; } double Math::ease(double p_x, double p_c) { diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 2e1b9c989e0..fc76d96b2ee 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -66,7 +66,7 @@ public: static double floor(double p_x); static double ceil(double p_x); static double ease(double p_x, double p_c); - static int decimals(double p_step); + static int step_decimals(double p_step); static double stepify(double p_value,double p_step); static void seed(uint32_t x=0); static void randomize(); diff --git a/modules/gdscript/gd_functions.cpp b/modules/gdscript/gd_functions.cpp index b9815a5efd8..a565e866d03 100644 --- a/modules/gdscript/gd_functions.cpp +++ b/modules/gdscript/gd_functions.cpp @@ -304,7 +304,7 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va case MATH_DECIMALS: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); - r_ret=Math::decimals(*p_args[0]); + r_ret=Math::step_decimals(*p_args[0]); } break; case MATH_STEPIFY: { VALIDATE_ARG_COUNT(2); diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index 2b64d36a819..98e1a32aef0 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -39,7 +39,7 @@ Size2 SpinBox::get_minimum_size() const { void SpinBox::_value_changed(double) { - String value = String::num(get_val(),Math::decimals(get_step())); + String value = String::num(get_val(),Math::step_decimals(get_step())); if (prefix!="") value=prefix+" "+value; if (suffix!="") diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 82459ba0ab1..487f62ed441 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -1179,8 +1179,8 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2& Ref updown = cache.updown; - //String valtext = String::num( p_item->cells[i].val, Math::decimals( p_item->cells[i].step ) ); - String valtext = rtos( p_item->cells[i].val ); + String valtext = String::num( p_item->cells[i].val, Math::step_decimals( p_item->cells[i].step ) ); + //String valtext = rtos( p_item->cells[i].val ); font->draw( ci, text_pos, valtext, col, item_rect.size.x-updown->get_width()); if (!p_item->cells[i].editable) @@ -1746,7 +1746,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ } else { - editor_text=String::num( p_item->cells[col].val, Math::decimals( p_item->cells[col].step ) ); + editor_text=String::num( p_item->cells[col].val, Math::step_decimals( p_item->cells[col].step ) ); if (select_mode==SELECT_MULTI && get_tree()->get_last_event_id() == focus_in_id) bring_up_editor=false; @@ -2521,7 +2521,7 @@ bool Tree::edit_selected() { text_editor->set_pos( textedpos ); text_editor->set_size( rect.size); text_editor->clear(); - text_editor->set_text( c.mode==TreeItem::CELL_MODE_STRING?c.text:rtos(c.val) ); + text_editor->set_text( c.mode==TreeItem::CELL_MODE_STRING?c.text:String::num( c.val, Math::step_decimals( c.step ) ) ); text_editor->select_all(); if (c.mode==TreeItem::CELL_MODE_RANGE || c.mode==TreeItem::CELL_MODE_RANGE_EXPRESSION ) { From 60e19f77519caee64842319443cd19e20c699d81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= Date: Tue, 26 Jul 2016 23:19:41 +0200 Subject: [PATCH 33/63] Fix GraphEdit dragging issues at scales != 1 Works around the issue originally described in #5907 (that was then hijacked to describe the broader issue it exposes). --- scene/gui/graph_edit.cpp | 5 ++++- scene/gui/graph_edit.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 06b1c426900..9ad621b7aa6 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -548,7 +548,9 @@ void GraphEdit::_input_event(const InputEvent& p_ev) { if (p_ev.type==InputEvent::MOUSE_MOTION && dragging) { just_selected=true; - drag_accum+=Vector2(p_ev.mouse_motion.relative_x,p_ev.mouse_motion.relative_y); + // TODO: Remove local mouse pos hack if/when InputEventMouseMotion is fixed to support floats + //drag_accum+=Vector2(p_ev.mouse_motion.relative_x,p_ev.mouse_motion.relative_y); + drag_accum = get_local_mouse_pos() - drag_origin; for(int i=get_child_count()-1;i>=0;i--) { GraphNode *gn=get_child(i)->cast_to(); if (gn && gn->is_selected()) @@ -665,6 +667,7 @@ void GraphEdit::_input_event(const InputEvent& p_ev) { dragging = true; drag_accum = Vector2(); + drag_origin = get_local_mouse_pos(); just_selected = !gn->is_selected(); if(!gn->is_selected() && !Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { for (int i = 0; i < get_child_count(); i++) { diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h index ac4e71ba49c..ed6838ac1d7 100644 --- a/scene/gui/graph_edit.h +++ b/scene/gui/graph_edit.h @@ -92,6 +92,7 @@ private: bool dragging; bool just_selected; Vector2 drag_accum; + Point2 drag_origin; // Workaround for GH-5907 float zoom; From 759e20aac69eca8beeca95a0f321c6a3f41f435f Mon Sep 17 00:00:00 2001 From: Dima Granetchi Date: Tue, 26 Jul 2016 22:17:41 +0300 Subject: [PATCH 34/63] Command-F focus filter input field in project manager --- tools/editor/project_manager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/editor/project_manager.cpp b/tools/editor/project_manager.cpp index caf116523ae..dd634e51ee3 100644 --- a/tools/editor/project_manager.cpp +++ b/tools/editor/project_manager.cpp @@ -692,6 +692,10 @@ void ProjectManager::_unhandled_input(const InputEvent& p_ev) { } } break; + case KEY_F: { + if (k.mod.command) this->project_filter->search_box->grab_focus(); + else scancode_handled = false; + } break; default: { scancode_handled = false; } break; From 535a6f9faf21f1f8cbd0f4580de47cfc231a625d Mon Sep 17 00:00:00 2001 From: Pawel Kowal Date: Wed, 27 Jul 2016 15:49:15 +0200 Subject: [PATCH 35/63] Array has() documentation --- doc/base/classes.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/base/classes.xml b/doc/base/classes.xml index d741dbbb656..dc24231dd03 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -4546,6 +4546,15 @@ Searches the array in reverse order for a value and returns its index or -1 if not found. + + + + + + + Return true if the array contains given value. [code][ "inside", 7 ].has("inside") == true, [ "inside", 7 ].has("outside") == false, [ "inside", 7 ].has(7) == true, [ "inside", 7 ].has("7") == false[/code] + + From 2150855fafd76f881bf5b1389d7740216981aaf0 Mon Sep 17 00:00:00 2001 From: Bojidar Marinov Date: Wed, 27 Jul 2016 17:59:42 +0300 Subject: [PATCH 36/63] Fix reading of empty StringArray-s in .tscn Closes #5912 --- core/variant_parser.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp index dce873a306f..023605a952e 100644 --- a/core/variant_parser.cpp +++ b/core/variant_parser.cpp @@ -1233,7 +1233,9 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in } get_token(p_stream,token,line,r_err_str); - if (token.type!=TK_STRING) { + if (token.type==TK_PARENTHESIS_CLOSE) { + break; + } else if (token.type!=TK_STRING) { r_err_str="Expected string"; return ERR_PARSE_ERROR; } From eefca1ada97a6bc5db38936d23da323a78b2044d Mon Sep 17 00:00:00 2001 From: Ignacio Etcheverry Date: Tue, 26 Jul 2016 17:19:49 +0200 Subject: [PATCH 37/63] Prettier str() for some math types --- core/math/math_2d.cpp | 2 +- core/math/math_2d.h | 8 ++++---- core/math/matrix3.cpp | 13 ++++++++++--- core/math/quat.cpp | 2 +- core/math/vector3.cpp | 2 +- 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/core/math/math_2d.cpp b/core/math/math_2d.cpp index 0e2060008c5..cf01e972a40 100644 --- a/core/math/math_2d.cpp +++ b/core/math/math_2d.cpp @@ -658,5 +658,5 @@ Matrix32 Matrix32::interpolate_with(const Matrix32& p_transform, float p_c) cons Matrix32::operator String() const { - return String(String()+elements[0]+", "+elements[1]+", "+elements[2]); + return "("+String(String()+elements[0]+", "+elements[1]+", "+elements[2])+")"; } diff --git a/core/math/math_2d.h b/core/math/math_2d.h index ad4655b8f78..5f511c933eb 100644 --- a/core/math/math_2d.h +++ b/core/math/math_2d.h @@ -157,7 +157,7 @@ struct Vector2 { float get_aspect() const { return width/height; } - operator String() const { return String::num(x)+","+String::num(y); } + operator String() const { return "("+String::num(x)+", "+String::num(y)+")"; } _FORCE_INLINE_ Vector2(float p_x,float p_y) { x=p_x; y=p_y; } _FORCE_INLINE_ Vector2() { x=0; y=0; } @@ -356,7 +356,7 @@ struct Rect2 { } - operator String() const { return String(pos)+","+String(size); } + operator String() const { return "("+String(pos)+", "+String(size)+")"; } Rect2() {} Rect2( float p_x, float p_y, float p_width, float p_height) { pos=Point2(p_x,p_y); size=Size2( p_width, p_height ); } @@ -409,7 +409,7 @@ struct Point2i { float get_aspect() const { return width/(float)height; } - operator String() const { return String::num(x)+","+String::num(y); } + operator String() const { return "("+String::num(x)+", "+String::num(y)+")"; } operator Vector2() const { return Vector2(x,y); } inline Point2i(const Vector2& p_vec2) { x=(int)p_vec2.x; y=(int)p_vec2.y; } @@ -540,7 +540,7 @@ struct Rect2i { } - operator String() const { return String(pos)+","+String(size); } + operator String() const { return "("+String(pos)+", "+String(size)+")"; } operator Rect2() const { return Rect2(pos,size); } Rect2i(const Rect2& p_r2) { pos=p_r2.pos; size=p_r2.size; } diff --git a/core/math/matrix3.cpp b/core/math/matrix3.cpp index 71e6b622123..7b811c245cf 100644 --- a/core/math/matrix3.cpp +++ b/core/math/matrix3.cpp @@ -233,19 +233,26 @@ bool Matrix3::operator!=(const Matrix3& p_matrix) const { Matrix3::operator String() const { - String mtx; + String mtx("("); for (int i=0;i<3;i++) { + if (i!=0) + mtx+=", "; + + mtx+="("; + for (int j=0;j<3;j++) { - if (i!=0 || j!=0) + if (j!=0) mtx+=", "; mtx+=rtos( elements[i][j] ); } + + mtx+=")"; } - return mtx; + return mtx+")"; } Matrix3::operator Quat() const { diff --git a/core/math/quat.cpp b/core/math/quat.cpp index c6c12129b30..5457638adaf 100644 --- a/core/math/quat.cpp +++ b/core/math/quat.cpp @@ -252,7 +252,7 @@ Quat Quat::cubic_slerp(const Quat& q, const Quat& prep, const Quat& postq,const Quat::operator String() const { - return String::num(x)+","+String::num(y)+","+ String::num(z)+","+ String::num(w); + return "("+String::num(x)+", "+String::num(y)+", "+ String::num(z)+", "+ String::num(w)+")"; } Quat::Quat(const Vector3& axis, const real_t& angle) { diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp index 8afd73f482b..8a0a6e963d5 100644 --- a/core/math/vector3.cpp +++ b/core/math/vector3.cpp @@ -182,5 +182,5 @@ Vector3 Vector3::cubic_interpolate(const Vector3& p_b,const Vector3& p_pre_a, co # endif Vector3::operator String() const { - return (rtos(x)+", "+rtos(y)+", "+rtos(z)); + return "("+(rtos(x)+", "+rtos(y)+", "+rtos(z))+")"; } From 9df192d8ec2a332f62f2dae2634828abcd9015c4 Mon Sep 17 00:00:00 2001 From: Ignacio Etcheverry Date: Wed, 27 Jul 2016 17:29:51 +0200 Subject: [PATCH 38/63] Project Settings: Use containers for the Input Map tab content --- tools/editor/project_settings.cpp | 33 ++++++++++++++++--------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/tools/editor/project_settings.cpp b/tools/editor/project_settings.cpp index 6be1abf52f5..e8d22143ee9 100644 --- a/tools/editor/project_settings.cpp +++ b/tools/editor/project_settings.cpp @@ -1375,34 +1375,35 @@ ProjectSettings::ProjectSettings(EditorData *p_data) { input_base->set_area_as_parent_rect();; tab_container->add_child(input_base); + VBoxContainer *vbc = memnew( VBoxContainer ); + input_base->add_child(vbc); + vbc->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN, 5 ); + vbc->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END, 5 ); + vbc->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN, 5 ); + vbc->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END, 5 ); + l = memnew( Label ); - input_base->add_child(l); + vbc->add_child(l); l->set_pos(Point2(6,5)); l->set_text(TTR("Action:")); + hbc = memnew( HBoxContainer ); + vbc->add_child(hbc); + action_name = memnew( LineEdit ); - action_name->set_anchor(MARGIN_RIGHT,ANCHOR_RATIO); - action_name->set_begin( Point2(5,25) ); - action_name->set_end( Point2(0.85,26) ); - input_base->add_child(action_name); + action_name->set_h_size_flags(SIZE_EXPAND_FILL); + hbc->add_child(action_name); action_name->connect("text_entered",this,"_action_adds"); add = memnew( Button ); - input_base->add_child(add); - add->set_anchor(MARGIN_LEFT,ANCHOR_RATIO); - add->set_begin( Point2(0.86,25) ); - add->set_anchor(MARGIN_RIGHT,ANCHOR_END); - add->set_end( Point2(5,26) ); + hbc->add_child(add); + add->set_custom_minimum_size(Size2(150, 0)); add->set_text(TTR("Add")); add->connect("pressed",this,"_action_add"); input_editor = memnew( Tree ); - input_base->add_child(input_editor); - input_editor->set_area_as_parent_rect(); - input_editor->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN, 55 ); - input_editor->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END, 35 ); - input_editor->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN, 5 ); - input_editor->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END, 5 ); + vbc->add_child(input_editor); + input_editor->set_v_size_flags(SIZE_EXPAND_FILL); input_editor->connect("item_edited",this,"_action_edited"); input_editor->connect("cell_selected",this,"_action_selected"); input_editor->connect("button_pressed",this,"_action_button_pressed"); From b48fd16add3669219ad38c27f7db7fc2d5e32130 Mon Sep 17 00:00:00 2001 From: George Marques Date: Wed, 27 Jul 2016 12:34:29 -0300 Subject: [PATCH 39/63] Improve Windows application details --- platform/windows/godot_res.rc | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/platform/windows/godot_res.rc b/platform/windows/godot_res.rc index 5f1e951e0f5..c1754afa8cd 100644 --- a/platform/windows/godot_res.rc +++ b/platform/windows/godot_res.rc @@ -3,12 +3,18 @@ #define _STR(m_x) #m_x #define _MKSTR(m_x) _STR(m_x) #endif +#ifndef VERSION_PATCH +#define VERSION_PATCH 0 +#define PATCH_STRING +#else +#define PATCH_STRING "." _MKSTR(VERSION_PATCH) +#endif GODOT_ICON ICON platform/windows/godot.ico 1 VERSIONINFO -FILEVERSION VERSION_MAJOR,VERSION_MINOR,0,0 -PRODUCTVERSION VERSION_MAJOR,VERSION_MINOR,0,0 +FILEVERSION VERSION_MAJOR,VERSION_MINOR,VERSION_PATCH,0 +PRODUCTVERSION VERSION_MAJOR,VERSION_MINOR,VERSION_PATCH,0 FILEOS 4 FILETYPE 1 BEGIN @@ -18,12 +24,12 @@ BEGIN BEGIN VALUE "CompanyName", "Godot Engine" VALUE "FileDescription", _MKSTR(VERSION_NAME) " Editor (" _MKSTR(VERSION_STATUS) ")" - VALUE "FileVersion", _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) "."_MKSTR(VERSION_REVISION) + VALUE "FileVersion", _MKSTR(VERSION_MAJOR),_MKSTR(VERSION_MINOR),_MKSTR(VERSION_PATCH) VALUE "ProductName", _MKSTR(VERSION_NAME) VALUE "Licence", "MIT" VALUE "LegalCopyright", "Copyright (c) 2007-" _MKSTR(VERSION_YEAR) " Juan Linietsky, Ariel Manzur" VALUE "Info", "http://www.godotengine.org" - VALUE "ProductVersion", _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) "."_MKSTR(VERSION_REVISION) + VALUE "ProductVersion", _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) PATCH_STRING "." _MKSTR(VERSION_REVISION) END END BLOCK "VarFileInfo" From cf851f7ed432134adb1da0077995a3ff26cc404d Mon Sep 17 00:00:00 2001 From: Ignacio Etcheverry Date: Wed, 27 Jul 2016 18:11:55 +0200 Subject: [PATCH 40/63] AboutDialog: Popup respecting its minimum size --- tools/editor/editor_node.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 2839708f8da..f27a7534641 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -2842,7 +2842,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { } break; case SETTINGS_ABOUT: { - about->popup_centered(Size2(500,130)*EDSCALE); + about->popup_centered_minsize(Size2(500,130)*EDSCALE); } break; case SOURCES_REIMPORT: { From 35cb8ff89e1c1871e7ad3383b524b2ebf82dfa3e Mon Sep 17 00:00:00 2001 From: Ignacio Etcheverry Date: Wed, 27 Jul 2016 19:32:46 +0200 Subject: [PATCH 41/63] LineEdit: Fix event handled as text when a mod key is pressed --- scene/gui/line_edit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 89c235e101f..fcea12fd6b7 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -468,7 +468,7 @@ void LineEdit::_input_event(InputEvent p_event) { if (handled) { accept_event(); - } else { + } else if (!k.mod.alt && !k.mod.command) { if (k.unicode>=32 && k.scancode!=KEY_DELETE) { if (editable) { From 0bc589a0c7a12c80f4e365724586174e2e7c9dbd Mon Sep 17 00:00:00 2001 From: George Marques Date: Wed, 27 Jul 2016 15:35:49 -0300 Subject: [PATCH 42/63] Fix Windows resource script --- platform/windows/godot_res.rc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/windows/godot_res.rc b/platform/windows/godot_res.rc index c1754afa8cd..b86869d316e 100644 --- a/platform/windows/godot_res.rc +++ b/platform/windows/godot_res.rc @@ -23,8 +23,8 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Godot Engine" - VALUE "FileDescription", _MKSTR(VERSION_NAME) " Editor (" _MKSTR(VERSION_STATUS) ")" - VALUE "FileVersion", _MKSTR(VERSION_MAJOR),_MKSTR(VERSION_MINOR),_MKSTR(VERSION_PATCH) + VALUE "FileDescription", _MKSTR(VERSION_NAME) " Editor" + VALUE "FileVersion", _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) "." _MKSTR(VERSION_PATCH) VALUE "ProductName", _MKSTR(VERSION_NAME) VALUE "Licence", "MIT" VALUE "LegalCopyright", "Copyright (c) 2007-" _MKSTR(VERSION_YEAR) " Juan Linietsky, Ariel Manzur" From 2d4c4b6ea9947607227e55682d195ebd05d383c6 Mon Sep 17 00:00:00 2001 From: Ignacio Etcheverry Date: Thu, 28 Jul 2016 14:41:15 +0200 Subject: [PATCH 43/63] Fix regression with str() improvements for math types --- core/math/math_2d.cpp | 2 +- core/math/math_2d.h | 8 ++++---- core/math/matrix3.cpp | 13 +++---------- core/math/quat.cpp | 2 +- core/math/vector3.cpp | 2 +- core/variant.cpp | 40 ++++++++++++++++++++++++++++++++++------ 6 files changed, 44 insertions(+), 23 deletions(-) diff --git a/core/math/math_2d.cpp b/core/math/math_2d.cpp index cf01e972a40..0e2060008c5 100644 --- a/core/math/math_2d.cpp +++ b/core/math/math_2d.cpp @@ -658,5 +658,5 @@ Matrix32 Matrix32::interpolate_with(const Matrix32& p_transform, float p_c) cons Matrix32::operator String() const { - return "("+String(String()+elements[0]+", "+elements[1]+", "+elements[2])+")"; + return String(String()+elements[0]+", "+elements[1]+", "+elements[2]); } diff --git a/core/math/math_2d.h b/core/math/math_2d.h index 5f511c933eb..fbf700fb9c2 100644 --- a/core/math/math_2d.h +++ b/core/math/math_2d.h @@ -157,7 +157,7 @@ struct Vector2 { float get_aspect() const { return width/height; } - operator String() const { return "("+String::num(x)+", "+String::num(y)+")"; } + operator String() const { return String::num(x)+", "+String::num(y); } _FORCE_INLINE_ Vector2(float p_x,float p_y) { x=p_x; y=p_y; } _FORCE_INLINE_ Vector2() { x=0; y=0; } @@ -356,7 +356,7 @@ struct Rect2 { } - operator String() const { return "("+String(pos)+", "+String(size)+")"; } + operator String() const { return String(pos)+", "+String(size); } Rect2() {} Rect2( float p_x, float p_y, float p_width, float p_height) { pos=Point2(p_x,p_y); size=Size2( p_width, p_height ); } @@ -409,7 +409,7 @@ struct Point2i { float get_aspect() const { return width/(float)height; } - operator String() const { return "("+String::num(x)+", "+String::num(y)+")"; } + operator String() const { return String::num(x)+", "+String::num(y); } operator Vector2() const { return Vector2(x,y); } inline Point2i(const Vector2& p_vec2) { x=(int)p_vec2.x; y=(int)p_vec2.y; } @@ -540,7 +540,7 @@ struct Rect2i { } - operator String() const { return "("+String(pos)+", "+String(size)+")"; } + operator String() const { return String(pos)+", "+String(size); } operator Rect2() const { return Rect2(pos,size); } Rect2i(const Rect2& p_r2) { pos=p_r2.pos; size=p_r2.size; } diff --git a/core/math/matrix3.cpp b/core/math/matrix3.cpp index 7b811c245cf..71e6b622123 100644 --- a/core/math/matrix3.cpp +++ b/core/math/matrix3.cpp @@ -233,26 +233,19 @@ bool Matrix3::operator!=(const Matrix3& p_matrix) const { Matrix3::operator String() const { - String mtx("("); + String mtx; for (int i=0;i<3;i++) { - if (i!=0) - mtx+=", "; - - mtx+="("; - for (int j=0;j<3;j++) { - if (j!=0) + if (i!=0 || j!=0) mtx+=", "; mtx+=rtos( elements[i][j] ); } - - mtx+=")"; } - return mtx+")"; + return mtx; } Matrix3::operator Quat() const { diff --git a/core/math/quat.cpp b/core/math/quat.cpp index 5457638adaf..73124e5e8ee 100644 --- a/core/math/quat.cpp +++ b/core/math/quat.cpp @@ -252,7 +252,7 @@ Quat Quat::cubic_slerp(const Quat& q, const Quat& prep, const Quat& postq,const Quat::operator String() const { - return "("+String::num(x)+", "+String::num(y)+", "+ String::num(z)+", "+ String::num(w)+")"; + return String::num(x)+", "+String::num(y)+", "+ String::num(z)+", "+ String::num(w); } Quat::Quat(const Vector3& axis, const real_t& angle) { diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp index 8a0a6e963d5..8afd73f482b 100644 --- a/core/math/vector3.cpp +++ b/core/math/vector3.cpp @@ -182,5 +182,5 @@ Vector3 Vector3::cubic_interpolate(const Vector3& p_b,const Vector3& p_pre_a, co # endif Vector3::operator String() const { - return "("+(rtos(x)+", "+rtos(y)+", "+rtos(z))+")"; + return (rtos(x)+", "+rtos(y)+", "+rtos(z)); } diff --git a/core/variant.cpp b/core/variant.cpp index 31321dc0f39..a78c07d819e 100644 --- a/core/variant.cpp +++ b/core/variant.cpp @@ -1515,15 +1515,43 @@ Variant::operator String() const { case INT: return String::num(_data._int); case REAL: return String::num(_data._real); case STRING: return *reinterpret_cast(_data._mem); - case VECTOR2: return operator Vector2(); - case RECT2: return operator Rect2(); - case MATRIX32: return operator Matrix32(); - case VECTOR3: return operator Vector3(); + case VECTOR2: return "("+operator Vector2()+")"; + case RECT2: return "("+operator Rect2()+")"; + case MATRIX32: { + + Matrix32 mat32 = operator Matrix32(); + return "("+Variant(mat32.elements[0]).operator String()+", "+Variant(mat32.elements[1]).operator String()+", "+Variant(mat32.elements[2]).operator String()+")"; + } break; + case VECTOR3: return "("+operator Vector3()+")"; case PLANE: return operator Plane(); //case QUAT: case _AABB: return operator AABB(); - case QUAT: return operator Quat(); - case MATRIX3: return operator Matrix3(); + case QUAT: return "("+operator Quat()+")"; + case MATRIX3: { + + Matrix3 mat3 = operator Matrix3(); + + String mtx("("); + for (int i=0;i<3;i++) { + + if (i!=0) + mtx+=", "; + + mtx+="("; + + for (int j=0;j<3;j++) { + + if (j!=0) + mtx+=", "; + + mtx+=Variant( mat3.elements[i][j] ).operator String(); + } + + mtx+=")"; + } + + return mtx+")"; + } break; case TRANSFORM: return operator Transform(); case NODE_PATH: return operator NodePath(); case INPUT_EVENT: return operator InputEvent(); From 740dea7de7ca9df8034076ee2c83fe7c0203b087 Mon Sep 17 00:00:00 2001 From: Paulb23 Date: Thu, 28 Jul 2016 15:47:47 +0100 Subject: [PATCH 44/63] Exposed enable syntax highlighting to properties --- scene/gui/text_edit.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index af04fbd2017..b265ef840a5 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -4508,6 +4508,7 @@ void TextEdit::_bind_methods() { ObjectTypeDB::bind_method(_MD("menu_option"),&TextEdit::menu_option); ObjectTypeDB::bind_method(_MD("get_menu:PopupMenu"),&TextEdit::get_menu); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "syntax_highlighting"), _SCS("set_syntax_coloring"), _SCS("is_syntax_coloring_enabled")); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_line_numbers"), _SCS("set_show_line_numbers"), _SCS("is_show_line_numbers_enabled")); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_all_occurrences"), _SCS("set_highlight_all_occurrences"), _SCS("is_highlight_all_occurrences_enabled")); From 08ba6086be75aac58748417808fed5462608f498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= Date: Thu, 28 Jul 2016 19:03:32 +0200 Subject: [PATCH 45/63] World2D: Fix typo in default_density deprecation check --- scene/resources/world_2d.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp index 6b329a1a73f..4c963da5b40 100644 --- a/scene/resources/world_2d.cpp +++ b/scene/resources/world_2d.cpp @@ -407,7 +407,7 @@ World2D::World2D() { Physics2DServer::get_singleton()->area_set_param(space,Physics2DServer::AREA_PARAM_GRAVITY,GLOBAL_DEF("physics_2d/default_gravity",98)); Physics2DServer::get_singleton()->area_set_param(space,Physics2DServer::AREA_PARAM_GRAVITY_VECTOR,GLOBAL_DEF("physics_2d/default_gravity_vector",Vector2(0,1))); // TODO: Remove this deprecation warning and compatibility code for 2.2 or 3.0 - if (Globals::get_singleton()->get("physics_2d/default_density") && !Globals::get_singleton()->get("physics_2d/default_linear_damp)")) { + if (Globals::get_singleton()->get("physics_2d/default_density") && !Globals::get_singleton()->get("physics_2d/default_linear_damp")) { WARN_PRINT("Deprecated parameter 'physics_2d/default_density'. It was renamed to 'physics_2d/default_linear_damp', adjusting your project settings accordingly (make sure to adjust scripts that potentially rely on 'physics_2d/default_density'."); Globals::get_singleton()->set("physics_2d/default_linear_damp", Globals::get_singleton()->get("physics_2d/default_density")); Globals::get_singleton()->set_persisting("physics_2d/default_linear_damp", true); From 3cdb5e0d1fff7a4d4b1dc1dcca4d024192df13d2 Mon Sep 17 00:00:00 2001 From: George Marques Date: Thu, 28 Jul 2016 21:23:05 -0300 Subject: [PATCH 46/63] Fix editor icons source file generation Also removes the unused make_icons.py file. --- tools/editor/icons/SCsub | 5 +--- tools/editor/icons/make_icons.py | 48 -------------------------------- 2 files changed, 1 insertion(+), 52 deletions(-) delete mode 100644 tools/editor/icons/make_icons.py diff --git a/tools/editor/icons/SCsub b/tools/editor/icons/SCsub index f2f5dcca48d..bc104294cb6 100644 --- a/tools/editor/icons/SCsub +++ b/tools/editor/icons/SCsub @@ -37,12 +37,9 @@ def make_editor_icons_action(target, source, env): pngf.close(); var_str=os.path.basename(x)[:-4]+"_hidpi_png"; -#print("TRY OPEN: "+os.path.dirname(x)+"/2x/"+os.path.basename(x)+"\n") try: - pngf = open(os.path.dirname(x)+"/2x/"+os.path.basename(x)) - - #print(var_str) + pngf = open(os.path.dirname(x)+"/2x/"+os.path.basename(x), "rb") s.write("static const unsigned char "+ var_str +"[]={\n"); diff --git a/tools/editor/icons/make_icons.py b/tools/editor/icons/make_icons.py deleted file mode 100644 index e06cbac7208..00000000000 --- a/tools/editor/icons/make_icons.py +++ /dev/null @@ -1,48 +0,0 @@ - -import glob - -pixmaps = glob.glob("*.png") - -f = open("../editor_icons.cpp","wb") - - -f.write("#include \"editor_icons.h\"\n\n") -f.write("#include \"scene/resources/theme.h\"\n\n") - -for x in pixmaps: - - var_str=x[:-4]+"_png"; - - f.write("static const unsigned char "+ var_str +"[]={\n"); - - pngf=open(x,"rb"); - - b=pngf.read(1); - while(len(b)==1): - f.write(hex(ord(b))) - b=pngf.read(1); - if (len(b)==1): - f.write(",") - - f.write("\n};\n\n\n"); - pngf.close(); - -f.write("static Ref make_icon(const uint8_t* p_png) {\n") -f.write("\tRef texture( memnew( ImageTexture ) );\n") -f.write("\ttexture->create_from_image( Image(p_png),ImageTexture::FLAG_FILTER );\n") -f.write("\treturn texture;\n") -f.write("}\n\n") - -f.write("void editor_register_icons(Ref p_theme) {\n\n") - - -for x in pixmaps: - - type=x[5:-4].title().replace("_",""); - var_str=x[:-4]+"_png"; - f.write("\tp_theme->set_icon(\""+type+"\",\"EditorIcons\",make_icon("+var_str+"));\n"); - -f.write("\n\n}\n\n"); -f.close() - - From 283530a70ba4c1a325dbd143f0c55e89b22f68df Mon Sep 17 00:00:00 2001 From: Dima Granetchi Date: Fri, 29 Jul 2016 03:33:59 +0300 Subject: [PATCH 47/63] keep selected_list up to date --- tools/editor/project_manager.cpp | 56 +++++++++++++++++++------------- tools/editor/project_manager.h | 1 + 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/tools/editor/project_manager.cpp b/tools/editor/project_manager.cpp index dd634e51ee3..9ca69935da1 100644 --- a/tools/editor/project_manager.cpp +++ b/tools/editor/project_manager.cpp @@ -510,6 +510,27 @@ void ProjectManager::_panel_draw(Node *p_hb) { } } +void ProjectManager::_update_project_buttons() +{ + String single_selected = ""; + if (selected_list.size() == 1) { + single_selected = selected_list.front()->key(); + } + + single_selected_main = ""; + for(int i=0;iget_child_count();i++) { + CanvasItem *item = scroll_childs->get_child(i)->cast_to(); + item->update(); + + if (single_selected!="" && single_selected == item->get_meta("name")) + single_selected_main = item->get_meta("main_scene"); + } + + erase_btn->set_disabled(selected_list.size()<1); + open_btn->set_disabled(selected_list.size()<1); + run_btn->set_disabled(selected_list.size()<1 || (selected_list.size()==1 && single_selected_main=="")); +} + void ProjectManager::_panel_input(const InputEvent& p_ev,Node *p_hb) { if (p_ev.type==InputEvent::MOUSE_BUTTON && p_ev.mouse_button.pressed && p_ev.mouse_button.button_index==BUTTON_LEFT) { @@ -557,23 +578,7 @@ void ProjectManager::_panel_input(const InputEvent& p_ev,Node *p_hb) { } } - String single_selected = ""; - if (selected_list.size() == 1) { - single_selected = selected_list.front()->key(); - } - - single_selected_main = ""; - for(int i=0;iget_child_count();i++) { - CanvasItem *item = scroll_childs->get_child(i)->cast_to(); - item->update(); - - if (single_selected!="" && single_selected == item->get_meta("name")) - single_selected_main = item->get_meta("main_scene"); - } - - erase_btn->set_disabled(selected_list.size()<1); - open_btn->set_disabled(selected_list.size()<1); - run_btn->set_disabled(selected_list.size()<1 || (selected_list.size()==1 && single_selected_main=="")); + _update_project_buttons(); if (p_ev.mouse_button.doubleclick) _open_project(); //open if doubleclicked @@ -739,6 +744,8 @@ void ProjectManager::_load_recent_projects() { memdelete( scroll_childs->get_child(0)); } + Map selected_list_copy = selected_list; + List properties; EditorSettings::get_singleton()->get_property_list(&properties); @@ -845,6 +852,8 @@ void ProjectManager::_load_recent_projects() { main_scene = cf->get_value("application","main_scene"); } + selected_list_copy.erase(project); + HBoxContainer *hb = memnew( HBoxContainer ); hb->set_meta("name",project); hb->set_meta("main_scene",main_scene); @@ -882,12 +891,15 @@ void ProjectManager::_load_recent_projects() { scroll_childs->add_child(hb); } - + + for (Map::Element *E = selected_list_copy.front();E;E = E->next()) { + String key = E->key(); + selected_list.erase(key); + } + scroll->set_v_scroll(0); - - erase_btn->set_disabled(selected_list.size()<1); - open_btn->set_disabled(selected_list.size()<1); - run_btn->set_disabled(selected_list.size()<1 || (selected_list.size()==1 && single_selected_main=="")); + + _update_project_buttons(); EditorSettings::get_singleton()->save(); diff --git a/tools/editor/project_manager.h b/tools/editor/project_manager.h index 74d1d3693cd..fac1fc77458 100644 --- a/tools/editor/project_manager.h +++ b/tools/editor/project_manager.h @@ -82,6 +82,7 @@ class ProjectManager : public Control { void _new_project(); void _erase_project(); void _erase_project_confirm(); + void _update_project_buttons(); void _exit_dialog(); void _scan_begin(const String& p_base); From 12ddc8703296abc5f1e88d9467f0ec0070fef103 Mon Sep 17 00:00:00 2001 From: "Daniel J. Ramirez" Date: Sun, 24 Jul 2016 11:41:03 -0500 Subject: [PATCH 48/63] New http request and tutorials icon Remove garbage in group icon --- tools/editor/icons/2x/icon_godot.png | Bin 1545 -> 1842 bytes .../editor/icons/2x/icon_h_t_t_p_request.png | Bin 180 -> 425 bytes tools/editor/icons/icon_godot.png | Bin 695 -> 769 bytes tools/editor/icons/icon_h_t_t_p_request.png | Bin 154 -> 301 bytes tools/editor/icons/source/icon_godot.svg | 28 +- tools/editor/icons/source/icon_group.svg | 1005 +---------------- .../icons/source/icon_h_t_t_p_request.svg | 78 +- 7 files changed, 77 insertions(+), 1034 deletions(-) diff --git a/tools/editor/icons/2x/icon_godot.png b/tools/editor/icons/2x/icon_godot.png index f789c791bd2f4c738efc7ad93002e3973d05d07a..94d87e23cc7477f27a03310d07bc5b3c2532470e 100644 GIT binary patch delta 1810 zcmV+t2krQY46+W8HGc-@NklK?jpL4!<@165Iibt@;JAYk9Q-rJ%U9DD%`C4dK z`iZT}?+uJu_U7?O-4j+SBIlJR?{~Y^;i8?H-l1}9Lj~9zMaxW9su6WaDb@oiy&lV! z2jhG`NmYvVh&p77P*pZZ(XwF+P{?#(T%eEV7w>Ud``>eS9tl&ZZ2_RjcunckhRSao zDgaTfD0$F3%74_QKC(Mp1^^GL7bI>Fs%ve-7l7UhDwwjF1AYf3m8Q20mEC^?bNBx( zI_Fupr5 z3{&N3vdXzVvvT?FQ>ndT*ek-#!o184egQT|(Kdw?^nVfEqSSt+%Q_UX!z7&6$_^bCvV@=_z7R7XkBsrP!lew?^+AO^oWm|Dia5NyoU)2wVad_Iq`2 z4|T;yxLJ0J_FFXoSQ93ZIAVJxl`1u9f50aIZL~^{9>n)wQEa5~a z&EnkdO@4k{#)`9k*p}}Mj~YK!0GYkMTNAs-~!p?6lc99QoL1 zjOK9XJYTI_pZep2ehnv$vJz_4c=w%m5b^bSr?Ze~?LGiTQy6xKi^@hfBEpv6lwvUX zI&MlrB=7zHJv<%{02eP@XsF2_sFdP#(FeZR zgo%B=z9dTd`I56AU^f4o12CISv~_rBzE&E*2M9=$dDW_)Ce7O%OmL5|btS^*@W<;gYNMcSJ9>nz zAa5NRFK_Jswba$$kgGK}W%ah7i8(4ZfbYMA3SjLXm-Sv3ZeJt$0q%y%K|6%OjVLbC zOkAXitMzw*{zmj@yokqIm}l=W*njd*&)<-d^z~;mlNViS>?U$%HkQa3dOF?o+;2xS zh7dJ&3X_(sWBQuygjoEO7#-bSZr|(nzZ=bAjG4C_Q$#f0u0TF1>nlwAqK|(u_cJU= zO(?%PVTCBWqv%zTA3m3rLP>QCr8TWQo0&}3^mwY9I{4(4n+w<5`1sS-pnto1n2m|H z@MLN%sqqmc$5}BLG}iC`D*(URG@qvrmY^$n%_vGbl|ZjRq{Y`>Lya1{j{Sqy4i72u zR=$^=%Ekl5{^WZ%rV}0-IL(C`HGcHRD^xbR0a%$f7EQtXWjCn2?Pkx0xxQmChoGSl zKnd+eME?*pimRG?zp-$#VSi2fI5bUh=2{aqP3_b)wX<&ign(j}5CdO3SRCNnnw?5` zs3E{tQq{th`a1xaj0RqQY6cTWg;V(VTL3838Drs&tTT2;(YXt?Z5bD8KPGX6g#{_G z)V6f^6PZE`e0OOo4R^Y@(bkDU1shT!B_V<_(P1P;TS%W6O>tGTe}C-{rFB#`x;^C$ zcSA)W#Gsu&x^2-}1z<1u%RJGwA_ap6NPze#izg{ITpJe?W=xE>V9*qf6aNf|SvGSt zY2%}*Z|m%-Zt8H?wsc5+Ygdej3{or5rJ)v`+_AXSzi7`ty$Yoc@kpcku*@r>zEGIA z_y`Q>gwDJrhehN`g@3C4pOseXI=WiYUpznnKw;jJlKTdk3+x6u9^{8%?MiTTYck9E z{ly;!XnGit>u`SxN6EAFjZ>4gUc*8SnI)*1 zz*t}e5Y-oQ2e=E=BkGbUxr}IM3iB4#43+y|qf`N?N6xK^01E&B07*qoM6N<$f~gCA A%m4rY delta 1510 zcmVSosgmsh--rJzw(d(3WOH1j>U1Oa?D6 zPGfXc{SQjdu6Xf4QB18Js{FUXU%F<26B%Y<8@jM_$^f znc^t^?8-aX@TF|-@P+vPvO->X_-NRZK@NItmicG;~*EcZLx)z6f^ozGqdCzoaWF!yeX62-^=MQ^`MhCX5`FJxYPoCm)IjIvjaAk0> z-EPlNPDBWgcwWfhha3551$x5$Bqn;|aEXZ?f+6Sg<7nVQcbMk3Adhc)oTQ{AM1*zg z*MD)SHR4DzJeuCS#KWuClAfLpzyn`>fP%sz4xH|A#5-Qc3OxVX8J<{L$e!9-dO{KE z-tD69%?ok3NHhjOIQr4j1jA8YZtmkJzuZkuvZ1Hn@a&&X(bg4mG#~(#+XKF<5qg~f zMg&`(@B6IOM6yynywiTgvHo$rs!?BqzkfXBD%*B&VdXvfD;DHW<+;7@a4{IcGJy zw`bGR8RFj`^m4o{$XoyE9#hCE^3uF4D$1lNJB5NQAC_gP+W8Lv3bK8y-+lDA7=Qh# zOGU$?5K~C?4m?!cF2nP$ouNAvr7+va_m&m0cGr<1@*QjElkAQ^K5o~*UZ3q4*vXZ1 zZ^a0_`u0W6Ug~B0nt1@EBqm@G6cDA)h1#!!;mEnmv2}~{t%v4M!x*9IpPiiV?BjfA zACD}&El$jvVDZh}N8)l%E-ND0ZGXk(j-Kn{RC^Bq9+$;)U%QhT8Ob!f`vCxgG`SkK z+}~7Q-FWzTYw*j*Ti+sgikEu}Gie=mYCQ=S-(6b7`#ljZ2E$n5JXQ-olR{ov61iz! z=Fdpu$hpfywLc!az}b%8=;`;bxK$y+GH?84bMYYoD6je30<}$}fa9>wzJJ9Votc?z zrllvja?`w6MyRfPFAlSOP7ZUYr_mk^_qTM0dRx0f+TI;WSJhE&6(R;H{_B>KV?)LA zZ3kB&Qp<#%>XV8as`B*)f5|==HVNzfOZKYjqEGd4BGQH}OFk5jGXT)wUvl)CrSpIn z0q4>6$)Zn`>gz`Ds(-rV^XEzYbB5+s)FuiKf~wmfFw!EwGX##dv?!CsTV0u zGy;IuIwhilhzhNBx>mqaL;=Q_keN>aLI5E%pNui#p9$#uzJCC4a7>5Mw!eU}?wJsq z*`C-}2dFmzVAPC-~DC%5e+qR#OGbd3hr9J>B147+>i2V=* zK@Ol^aK9d70bJPwOXt`{Yn?Ll7l!GP=!ob&j^oN2Za%t(IF2i3&V7Dn&fSl1E&!Oe zW+}KzX`^l~0Co`jVOICu1w>KQ5z!GqhoSDr%c-%v?jZme`k`r>8~~J3)vfp^kIS?P z?dG!^&v$n2@Jc_sb{n_L7_MRQ82U1^)DKU_?kWQW{Qe7W$mRR@*8{$;-iq1#mVeK{ bQ^1oSo86&rccDIP00000NkvXXu0mjfB4f2M delta 134 zcmV;10D1qZ1GE8d1~k-^R`YuF<_De46c&}YVWtY oI7I@te-z+!f9vxEG=PYRY`(uTeEsuy!TTHh;EBL_t(IjfIk5NS$>U$3M^ep7WmN+$lY?;1tKUau>P6(hH%W zx#XCp;LTu-h}g}9AaKK=i{e~qu!VZMNJ)i7fmx*HpB+z5cQFRD$&zxeJg7NzTcORP z=G61PPZxSbh1>(bo8Ra8K7YQypRg-}pAD9Za#oc;qE!VI0Dr;rgAImAmLpmlJy+1Z zJ>RvvfG8C}fe5b!FI*V~5cIU7Zc$c%9R&;kR0SXu3K@X4$=rg51q}o4%{yx|XGE0B_tG?vDPrqU5-UP8o%T}8tf2aCuia%;* z@$LpUEb~K7gxV~R*Qdun`A&b0-O>8GdTshXqQH)GzV)((!=LNOZ@0C)rd>T=pPmS{ zSw^yp_c1r)BR|v8(aFr{4Ln{S_0iwy{$&P_*N4tc(SQC!JAFM}1k(3!O=l!`x_YsO z2c9P>DJ`Y7vj=}(5w5qq(%!eT+Y^Xya9CFOR=6IXgGh)lzTH z4o7#GWLXw&Q&?VEB^GI6J1;o-zLS@A@CAAMi)$lgFZ*A*H4`WI*)$Mn7>IG?sRQI> zrU5YV*MAZ>rsg@7pNY#bSXxbBxeNxz?vEJ@E9*ZFPtHHge=eQY>(l%lUnM7y#;aKw zv<*$uHZ)C6;0dyyew-AK$ye7Vc_uw2@#oxf+)?e5;&88*^^~iQ>Wct|$eJ(Jnmd^4 zSs%L_4*(p>*gv!QFtPs6@>+)NXwt!(9^3u808kW%d%e!uzB-V10rL^R&jz_@SpQaD z`k*8(+eu+<|6$WMPJ$c*$p%f|ATkd+Dk_5sSK{0L%EF1H=09dTCt_!b7>)n{002ov JPDHLkV1j1YV8H+Y delta 653 zcmV;80&@L<2Db%}Hh*kML_t(Ijh&ERNRwd{#((GizI~HzPB$A->9RzLqOhz8DpHb# z{efKfd~X2&dsYXih(F}SCVx)E zlNg=Ittxg|ym|4M&dzHLKYswg=BfaD*9QU6V{hrW+QFS$H&`0*{B$w*h)>R7maU>O z9ES3B0A#c#V`~70jZzxJVb*Tl!OIU{astwN_syEvSbwtr)kxCFzu7bt4nvqqW&X&c z%;&P#EGb%U_79F<*tL40;kF#ql>0!St@kZe^9!k7>;qtEY?3GM6YSrx7*i=GXVO@v zQoXM~b*PD{+3Qc=C8jr2___Qj#&~ju>Y$H}l>yrOW3>0js16phVo?z;r@^I%?V{4Ev8*xH@F z;+Zq!*dhQ8kuI;DDmVuc2L8w*uQDJPmG%9|?ZexX^6R9&wP&f3QTsq@K~{kFXR}U# n9uO_jw3)urbEJM~j`IUoFxI|`hEWFq0000g_vPEgJ$Ubnh@61}6cIUl?+d`8Cjr1TO^*=5`=apC`|j@{@HISD9oln=*^Y03 z0rGN)%NA_i#@26aTM5~I(VvvBsVX8W)>gyK%6`!FfbZ=9y!MXqd002ovPDHLk FV1nA1c#i-8 delta 107 zcmV-x0F?i&0-6DkHe^ppL_t(IjqQ%X3BWK6#AHvR{in(#bw5oBp@sI9PxP@54sozq zPqfw!HOC7CP%pWF0z!?PjcWGtQy%^T$iCw5>T4CV{R^e0dJ8tIIRUS-CsGvWkbM9E N002ovPDHLkV1oJ`E`I<3 diff --git a/tools/editor/icons/source/icon_godot.svg b/tools/editor/icons/source/icon_godot.svg index 927c3ee053b..419f23125b7 100644 --- a/tools/editor/icons/source/icon_godot.svg +++ b/tools/editor/icons/source/icon_godot.svg @@ -28,12 +28,12 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="22.627417" - inkscape:cx="4.9021021" - inkscape:cy="11.249083" + inkscape:zoom="32" + inkscape:cx="9.8470361" + inkscape:cy="9.8599985" inkscape:document-units="px" inkscape:current-layer="layer1" - showgrid="true" + showgrid="false" units="px" inkscape:snap-bbox="true" inkscape:bbox-paths="true" @@ -59,7 +59,7 @@ image/svg+xml - + @@ -146,5 +146,23 @@ + + + diff --git a/tools/editor/icons/source/icon_group.svg b/tools/editor/icons/source/icon_group.svg index c8d20af9ddf..a0a2f02af5d 100644 --- a/tools/editor/icons/source/icon_group.svg +++ b/tools/editor/icons/source/icon_group.svg @@ -28,9 +28,9 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="22.627417" - inkscape:cx="10.459761" - inkscape:cy="9.5219725" + inkscape:zoom="5.6568543" + inkscape:cx="14.789684" + inkscape:cy="26.718572" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="true" @@ -78,1005 +78,6 @@ d="M 7 1 L 7 3 L 7 7 L 3 7 C 3 6.9999766 2.554 7 2 7 C 1.446 7 1 6.9999766 1 7 L 1 9 L 1 13 C 1 13.000023 1.446 13 2 13 C 2.554 13 3 13.000023 3 13 L 3 9 L 7 9 L 7 13 L 3 13 C 2.9999766 13 3 13.446 3 14 C 3 14.554 2.9999766 15 3 15 L 7 15 C 7 15.000023 7.446 15 8 15 C 8.554 15 9 15.000023 9 15 L 9 13 L 9 9 L 13 9 C 13 9.0000234 13.446 9 14 9 C 14.554 9 15 9.0000234 15 9 L 15 7 L 15 3 C 15 2.9999766 14.554 3 14 3 C 13.446 3 13 2.9999766 13 3 L 13 7 L 9 7 L 9 3 L 13 3 C 13.000023 3 13 2.554 13 2 C 13 1.446 13.000023 1 13 1 L 9 1 C 9 0.99997659 8.554 1 8 1 C 7.446 1 7 0.99997659 7 1 z " id="rect4697" transform="translate(0,1036.3622)" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -28,9 +28,9 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="45.254836" - inkscape:cx="10.430372" - inkscape:cy="8.7048298" + inkscape:zoom="32.000001" + inkscape:cx="14.357316" + inkscape:cy="9.4289864" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="true" @@ -59,7 +59,7 @@ image/svg+xml - + @@ -73,18 +73,18 @@ id="rect4200" width="1" height="5" - x="0" - y="1042.3622" /> + x="1" + y="1046.3622" /> + x="6" + y="1046.3622" /> + x="9" + y="1046.3622" /> + x="13" + y="1046.3622" /> + x="15" + y="1046.3622" /> + x="13" + y="1048.3622" /> + + + + From 5035edb7fdff85749ab5640b9a7fda91b9d39012 Mon Sep 17 00:00:00 2001 From: Saracen Date: Fri, 29 Jul 2016 13:50:26 +0100 Subject: [PATCH 49/63] Explicitly initialize 'pending_auto_reload' to false. --- tools/editor/plugins/script_editor_plugin.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp index 4032a790d8c..be4b002d895 100644 --- a/tools/editor/plugins/script_editor_plugin.cpp +++ b/tools/editor/plugins/script_editor_plugin.cpp @@ -2749,6 +2749,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { completion_cache = memnew( EditorScriptCodeCompletionCache ); restoring_layout=false; waiting_update_names=false; + pending_auto_reload=false; auto_reload_running_scripts=false; editor=p_editor; From 9720e73e0480e454b580afc9499240bb08a823f3 Mon Sep 17 00:00:00 2001 From: Andreas Haas Date: Fri, 29 Jul 2016 17:06:37 +0200 Subject: [PATCH 50/63] Project Manager: Import projects using filesystem drag'n'drop. Can drop an engine.cfg file over the window to import it ;) --- tools/editor/project_manager.cpp | 17 +++++++++++++++++ tools/editor/project_manager.h | 1 + 2 files changed, 18 insertions(+) diff --git a/tools/editor/project_manager.cpp b/tools/editor/project_manager.cpp index 9ca69935da1..28d9738fee3 100644 --- a/tools/editor/project_manager.cpp +++ b/tools/editor/project_manager.cpp @@ -364,6 +364,12 @@ public: mode=p_mode; } + void import_from_file(const String& p_file) { + mode=MODE_IMPORT; + _file_selected(p_file); + ok_pressed(); + } + void show_dialog() { @@ -1097,6 +1103,14 @@ void ProjectManager::_install_project(const String& p_zip_path,const String& p_t npdialog->show_dialog(); } +void ProjectManager::_files_dropped(StringArray p_files, int p_screen) { + for (int i = 0; i < p_files.size(); i++) { + if (p_files[i].ends_with("engine.cfg")) { + npdialog->import_from_file(p_files[i]); + } + } +} + void ProjectManager::_bind_methods() { ObjectTypeDB::bind_method("_open_project",&ProjectManager::_open_project); @@ -1116,6 +1130,7 @@ void ProjectManager::_bind_methods() { ObjectTypeDB::bind_method("_unhandled_input",&ProjectManager::_unhandled_input); ObjectTypeDB::bind_method("_favorite_pressed",&ProjectManager::_favorite_pressed); ObjectTypeDB::bind_method("_install_project",&ProjectManager::_install_project); + ObjectTypeDB::bind_method("_files_dropped",&ProjectManager::_files_dropped); } @@ -1330,6 +1345,8 @@ ProjectManager::ProjectManager() { //get_ok()->set_text("Exit"); last_clicked = ""; + + SceneTree::get_singleton()->connect("files_dropped", this, "_files_dropped"); } diff --git a/tools/editor/project_manager.h b/tools/editor/project_manager.h index fac1fc77458..50bd7d94c89 100644 --- a/tools/editor/project_manager.h +++ b/tools/editor/project_manager.h @@ -95,6 +95,7 @@ class ProjectManager : public Control { void _panel_input(const InputEvent& p_ev,Node *p_hb); void _unhandled_input(const InputEvent& p_ev); void _favorite_pressed(Node *p_hb); + void _files_dropped(StringArray p_files, int p_screen); protected: From 6e137c02d26df269c9860ac69e9d8824e4b5336b Mon Sep 17 00:00:00 2001 From: Ignacio Etcheverry Date: Sat, 30 Jul 2016 01:11:02 +0200 Subject: [PATCH 51/63] Fix infinite loop when replacing text --- tools/editor/code_editor.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/editor/code_editor.cpp b/tools/editor/code_editor.cpp index ed7a46d70d2..d2bf070f1b9 100644 --- a/tools/editor/code_editor.cpp +++ b/tools/editor/code_editor.cpp @@ -188,7 +188,9 @@ void FindReplaceBar::_replace_all() { text_edit->cursor_set_line(0); text_edit->cursor_set_column(0); + String replace_text=get_replace_text(); int search_text_len=get_search_text().length(); + int rc=0; replace_all_mode = true; @@ -204,7 +206,7 @@ void FindReplaceBar::_replace_all() { if (match_from < prev_match) break; // done - prev_match=match_to; + prev_match=Point2i(result_line,result_col+replace_text.length()); text_edit->select(result_line,result_col,result_line,match_to.y); @@ -214,12 +216,12 @@ void FindReplaceBar::_replace_all() { continue; // replace but adjust selection bounds - text_edit->insert_text_at_cursor(get_replace_text()); + text_edit->insert_text_at_cursor(replace_text); if (match_to.x==selection_end.x) - selection_end.y+=get_replace_text().length() - get_search_text().length(); + selection_end.y+=replace_text.length()-search_text_len; } else { // just replace - text_edit->insert_text_at_cursor(get_replace_text()); + text_edit->insert_text_at_cursor(replace_text); } rc++; From 4755fe5576b05c94081bdcad5bd37523d5040150 Mon Sep 17 00:00:00 2001 From: Andreas Haas Date: Sat, 30 Jul 2016 12:38:42 +0200 Subject: [PATCH 52/63] UI navigation via JOYSTICK_MOTION. Previously, you could assign joystick axis events to "ui_*" actions but they had no effect. See https://godotengine.org/qa/6232 --- scene/main/viewport.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index f182f2c96cd..7970229c065 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -2095,6 +2095,7 @@ void Viewport::_gui_input_event(InputEvent p_event) { } break; case InputEvent::ACTION: case InputEvent::JOYSTICK_BUTTON: + case InputEvent::JOYSTICK_MOTION: case InputEvent::KEY: { From 09c4d65b64892f945aeb98a4abcedab42126c248 Mon Sep 17 00:00:00 2001 From: allkhor Date: Sun, 31 Jul 2016 00:18:30 +0600 Subject: [PATCH 53/63] Fix String::is_valid_integer() for single symbols + and - --- core/ustring.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/ustring.cpp b/core/ustring.cpp index 6788ada1bba..0d887210c3b 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -3491,7 +3491,7 @@ bool String::is_valid_integer() const { return false; int from=0; - if (operator[](0)=='+' || operator[](0)=='-') + if (len!=1 && (operator[](0)=='+' || operator[](0)=='-')) from++; for(int i=from;i Date: Sat, 30 Jul 2016 20:41:38 +0200 Subject: [PATCH 54/63] Document FuncRef, GDFunctionState, InstancePlaceholder, RID, World2D --- core/func_ref.cpp | 2 +- doc/base/classes.xml | 28 ++++++++++++++++++++++++++-- modules/gdscript/gd_editor.cpp | 2 +- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/core/func_ref.cpp b/core/func_ref.cpp index 29b06ae9a0f..644d8b5b63c 100644 --- a/core/func_ref.cpp +++ b/core/func_ref.cpp @@ -65,7 +65,7 @@ void FuncRef::_bind_methods() { mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i))); defargs.push_back(Variant()); } - ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"call_func",&FuncRef::call_func,mi,defargs); + ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"call_func:Variant",&FuncRef::call_func,mi,defargs); } diff --git a/doc/base/classes.xml b/doc/base/classes.xml index dc24231dd03..b7b0502eaad 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -660,7 +660,7 @@ - Stop the function execution and return the current state. Call resume on the state to resume execution. This makes the state invalid. + Stop the function execution and return the current state. Call [method GDFunctionState.resume] on the state to resume execution. This invalidates the state. Returns anything that was passed to the resume function call. If passed an object and a signal, the execution is resumed when the object's signal is emmited. @@ -13042,8 +13042,11 @@ + Reference to a function in an object. + In GDScript, functions are not [i]first-class objects[/i]. This means it is impossible to store them directly as variables, return them from another function, or pass them as arguments. + However, by creating a [FuncRef] using the [method @GDScript.funcref] function, a reference to a function in a given object can be created, passed around and called. @@ -13068,18 +13071,21 @@ + Call the referenced function with the given arguments. The argument count must correspond to the required number of arguments in the function. Returns the return value of the function call. + Set the name of the function to call on the object, without parentheses or any parameters. + Set the object on which to call the referenced function. This object must be of a type actually inheriting from [Object], not a built-in type such as [int], [Vector2] or [Dictionary]. @@ -13088,15 +13094,17 @@ + State of a function call after yielding. + Calling [method @GDScript.yield] within a function will cause that function to yield and return its current state as an object of this type. The yielded function call can then be resumed later by calling [method resume] on this state object. - Should put children to the top left corner instead of center of the container. + Check whether the function call may be resumed. This is not the case if the function state was already resumed. @@ -13105,6 +13113,9 @@ + Resume execution of the yielded function call. + If handed an argument, return the argument from the [method @GDScript.yield] call in the yielded function call. You can pass e.g. an [Array] to hand multiple arguments. + This function returns what the resumed function call returns, possibly another function state if yielded again. @@ -17235,20 +17246,25 @@ + Placeholder for the root [Node] of a [PackedScene]. + Turning on the option [b]Load As Placeholder[/b] for an instanced scene in the editor causes it to be replaced by an InstacePlaceholder when running the game. This makes it possible to delay actually loading the scene until calling [method replace_by_instance]. This is useful to avoid loading large scenes all at once by loading parts of it selectively. + The InstancePlaceholder does not have a transform. This causes any child nodes to be positioned relatively to the Viewport from point (0,0), rather than their parent as displayed in the editor. Replacing the placeholder with a scene with a transform will transform children relatively to their parent again. + Retrieve the path to the [PackedScene] resource file that is loaded by default when calling [method replace_by_instance]. + Replace this placeholder by the scene handed as an argument, or the original scene if no argument is given. As for all resources, the scene is loaded only if it's not loaded already. By manually loading the scene beforehand, delays caused by this function can be avoided. @@ -30280,8 +30296,10 @@ + Handle for a [Resource]'s unique ID. + The RID type is used to access the unique integer ID of a resource. They are opaque, so they do not grant access to the associated resource by themselves. They are used by and with the low-level Server classes such as [VisualServer]. @@ -30290,12 +30308,14 @@ + Create a new RID instance with the ID of a given resource. When not handed a valid resource, silently stores the unused ID 0. + Retrieve the ID of the referenced resource. @@ -46584,24 +46604,28 @@ + Retrieve the [RID] of this world's canvas resource. Used by the [VisualServer] for 2D drawing. + Retrieve the state of this world's physics space. This allows arbitrary querying for collision. + Retrieve the [RID] of this world's sound space resource. Used by the [SpatialSound2DServer] for 2D spatial audio. + Retrieve the [RID] of this world's physics space resource. Used by the [Physics2DServer] for 2D physics, treating it as both a space and an area. diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp index 520a8b18d86..b02e55cf9d5 100644 --- a/modules/gdscript/gd_editor.cpp +++ b/modules/gdscript/gd_editor.cpp @@ -297,7 +297,7 @@ void GDScriptLanguage::get_public_functions(List *p_functions) const } { MethodInfo mi; - mi.name="yield"; + mi.name="yield:GDFunctionState"; mi.arguments.push_back(PropertyInfo(Variant::OBJECT,"object")); mi.arguments.push_back(PropertyInfo(Variant::STRING,"signal")); mi.default_arguments.push_back(Variant::NIL); From a1c0fdac9a4ec1e8c2097b457a52e568f983c7d0 Mon Sep 17 00:00:00 2001 From: Dima Granetchi Date: Sun, 31 Jul 2016 01:04:16 +0300 Subject: [PATCH 55/63] fix run button availability check --- tools/editor/project_manager.cpp | 21 ++++++++++----------- tools/editor/project_manager.h | 3 --- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/tools/editor/project_manager.cpp b/tools/editor/project_manager.cpp index 28d9738fee3..f885fbba077 100644 --- a/tools/editor/project_manager.cpp +++ b/tools/editor/project_manager.cpp @@ -518,23 +518,23 @@ void ProjectManager::_panel_draw(Node *p_hb) { void ProjectManager::_update_project_buttons() { - String single_selected = ""; - if (selected_list.size() == 1) { - single_selected = selected_list.front()->key(); - } - - single_selected_main = ""; for(int i=0;iget_child_count();i++) { + CanvasItem *item = scroll_childs->get_child(i)->cast_to(); item->update(); - - if (single_selected!="" && single_selected == item->get_meta("name")) - single_selected_main = item->get_meta("main_scene"); + } + + bool has_runnable_scene = false; + for (Map::Element *E=selected_list.front(); E; E=E->next()) { + const String &selected_main = E->get(); + if (selected_main == "") continue; + has_runnable_scene = true; + break; } erase_btn->set_disabled(selected_list.size()<1); open_btn->set_disabled(selected_list.size()<1); - run_btn->set_disabled(selected_list.size()<1 || (selected_list.size()==1 && single_selected_main=="")); + run_btn->set_disabled(!has_runnable_scene); } void ProjectManager::_panel_input(const InputEvent& p_ev,Node *p_hb) { @@ -1072,7 +1072,6 @@ void ProjectManager::_erase_project_confirm() { EditorSettings::get_singleton()->save(); selected_list.clear(); last_clicked = ""; - single_selected_main=""; _load_recent_projects(); } diff --git a/tools/editor/project_manager.h b/tools/editor/project_manager.h index 50bd7d94c89..da570339059 100644 --- a/tools/editor/project_manager.h +++ b/tools/editor/project_manager.h @@ -60,7 +60,6 @@ class ProjectManager : public Control { VBoxContainer *scroll_childs; Map selected_list; // name -> main_scene String last_clicked; - String single_selected_main; bool importing; HBoxContainer *projects_hb; @@ -69,8 +68,6 @@ class ProjectManager : public Control { Control *gui_base; - void _item_doubleclicked(); - void _scan_projects(); From 5e011dcd0e4958f6bc59f64e024402af1ad1dc0d Mon Sep 17 00:00:00 2001 From: Dima Granetchi Date: Sun, 31 Jul 2016 01:10:13 +0300 Subject: [PATCH 56/63] dnd folder open scan window if engine.cfg not found --- tools/editor/project_manager.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/editor/project_manager.cpp b/tools/editor/project_manager.cpp index 28d9738fee3..20544d2f054 100644 --- a/tools/editor/project_manager.cpp +++ b/tools/editor/project_manager.cpp @@ -1104,11 +1104,17 @@ void ProjectManager::_install_project(const String& p_zip_path,const String& p_t } void ProjectManager::_files_dropped(StringArray p_files, int p_screen) { + bool import_project_file = false; for (int i = 0; i < p_files.size(); i++) { if (p_files[i].ends_with("engine.cfg")) { npdialog->import_from_file(p_files[i]); + import_project_file = true; } } + if (!import_project_file && p_files.size() > 0) { + scan_dir->set_current_dir(p_files[0]); + scan_dir->popup_centered_ratio(); + } } void ProjectManager::_bind_methods() { From 0b595f94c47a9144dbe9c200a8057558b0c4f839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= Date: Sun, 31 Jul 2016 20:46:00 +0200 Subject: [PATCH 57/63] Improve dialog title when scanning for projects --- tools/editor/project_manager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/editor/project_manager.cpp b/tools/editor/project_manager.cpp index daba5c9ebaa..90e655f1162 100644 --- a/tools/editor/project_manager.cpp +++ b/tools/editor/project_manager.cpp @@ -1270,6 +1270,7 @@ ProjectManager::ProjectManager() { scan_dir = memnew( FileDialog ); scan_dir->set_access(FileDialog::ACCESS_FILESYSTEM); scan_dir->set_mode(FileDialog::MODE_OPEN_DIR); + scan_dir->set_title(TTR("Select a Folder to Scan")); // must be after mode or it's overridden scan_dir->set_current_dir( EditorSettings::get_singleton()->get("global/default_project_path") ); gui_base->add_child(scan_dir); scan_dir->connect("dir_selected",this,"_scan_begin"); From ae1267d41cf15d9a5b40a4d2525f2cb151f6b17d Mon Sep 17 00:00:00 2001 From: Mario Schlack Date: Mon, 1 Aug 2016 16:30:09 +0800 Subject: [PATCH 58/63] Fix help page title indentation --- tools/editor/editor_help.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tools/editor/editor_help.cpp b/tools/editor/editor_help.cpp index 1fc157098cf..4ab86ad5125 100644 --- a/tools/editor/editor_help.cpp +++ b/tools/editor/editor_help.cpp @@ -943,10 +943,9 @@ Error EditorHelp::_goto_desc(const String& p_class,int p_vscr) { class_desc->add_newline(); } - class_desc->add_newline(); + class_desc->pop(); - - + class_desc->add_newline(); } if (cd.theme_properties.size()) { @@ -987,11 +986,10 @@ Error EditorHelp::_goto_desc(const String& p_class,int p_vscr) { class_desc->add_newline(); } - class_desc->add_newline(); class_desc->pop(); - - + class_desc->add_newline(); } + if (cd.signals.size()) { if (sort_methods) { From d7910f44d89e941772e1f54ffdc17d162795ba4a Mon Sep 17 00:00:00 2001 From: Paulb23 Date: Sun, 12 Jun 2016 16:47:29 +0100 Subject: [PATCH 59/63] Added Scene tree dock shortcuts --- tools/editor/scene_tree_dock.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tools/editor/scene_tree_dock.cpp b/tools/editor/scene_tree_dock.cpp index 35ddb494650..9e2b2266a56 100644 --- a/tools/editor/scene_tree_dock.cpp +++ b/tools/editor/scene_tree_dock.cpp @@ -48,11 +48,9 @@ void SceneTreeDock::_unhandled_key_input(InputEvent p_event) { if (get_viewport()->get_modal_stack_top()) return; //ignore because of modal window - uint32_t sc = p_event.key.get_scancode_with_modifiers(); if (!p_event.key.pressed || p_event.key.echo) return; - if (ED_IS_SHORTCUT("scene_tree/add_child_node", p_event)) { _tool_selected(TOOL_NEW); } @@ -83,9 +81,11 @@ void SceneTreeDock::_unhandled_key_input(InputEvent p_event) { else if (ED_IS_SHORTCUT("scene_tree/save_branch_as_scene", p_event)) { _tool_selected(TOOL_NEW_SCENE_FROM); } - switch(sc) { - case KEY_MASK_SHIFT|KEY_DELETE: { _tool_selected(TOOL_ERASE, true); } break; - case KEY_DELETE: { _tool_selected(TOOL_ERASE); } break; + else if (ED_IS_SHORTCUT("scene_tree/delete_no_confirm", p_event)) { + _tool_selected(TOOL_ERASE, true); + } + else if (ED_IS_SHORTCUT("scene_tree/delete", p_event)) { + _tool_selected(TOOL_ERASE); } } @@ -1769,7 +1769,7 @@ void SceneTreeDock::_tree_rmb(const Vector2& p_menu_pos) { } menu->add_separator(); - menu->add_icon_item(get_icon("Remove","EditorIcons"),TTR("Delete Node(s)"), TOOL_ERASE, KEY_DELETE); + menu->add_icon_shortcut(get_icon("Remove","EditorIcons"), ED_SHORTCUT("scene_tree/delete", TTR("Delete Node(s)"), KEY_DELETE), TOOL_ERASE); menu->set_size(Size2(1,1)); menu->set_pos(p_menu_pos); @@ -1846,6 +1846,8 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelec ED_SHORTCUT("scene_tree/reparent", TTR("Reparent")); ED_SHORTCUT("scene_tree/merge_from_scene", TTR("Merge From Scene")); ED_SHORTCUT("scene_tree/save_branch_as_scene", TTR("Save Branch as Scene")); + ED_SHORTCUT("scene_tree/delete_no_confirm", TTR("Delete (No Confirm)"), KEY_MASK_SHIFT|KEY_DELETE); + ED_SHORTCUT("scene_tree/delete", TTR("Delete"), KEY_DELETE); tb = memnew( ToolButton ); tb->connect("pressed",this,"_tool_selected",make_binds(TOOL_NEW, false)); From bee20910569d89cf36b6601eca2c6322f2947943 Mon Sep 17 00:00:00 2001 From: Dima Granetchi Date: Mon, 1 Aug 2016 01:59:31 +0300 Subject: [PATCH 60/63] Auto import project folder, confirm scan multiple folders or non-project folder --- tools/editor/project_manager.cpp | 56 +++++++++++++++++++++++++++----- tools/editor/project_manager.h | 2 ++ 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/tools/editor/project_manager.cpp b/tools/editor/project_manager.cpp index 90e655f1162..62b15d344da 100644 --- a/tools/editor/project_manager.cpp +++ b/tools/editor/project_manager.cpp @@ -1103,16 +1103,50 @@ void ProjectManager::_install_project(const String& p_zip_path,const String& p_t } void ProjectManager::_files_dropped(StringArray p_files, int p_screen) { - bool import_project_file = false; + Set folders_set; + DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); for (int i = 0; i < p_files.size(); i++) { - if (p_files[i].ends_with("engine.cfg")) { - npdialog->import_from_file(p_files[i]); - import_project_file = true; + String file = p_files[i]; + folders_set.insert(da->dir_exists(file) ? file : file.get_base_dir()); + } + memdelete(da); + if (folders_set.size()>0) { + StringArray folders; + for (Set::Element *E=folders_set.front();E;E=E->next()) { + folders.append(E->get()); + } + + bool confirm = true; + if (folders.size()==1) { + DirAccess *dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + if (dir->change_dir(folders[0])==OK) { + dir->list_dir_begin(); + String file = dir->get_next(); + while(confirm && file!=String()) { + if (!da->current_is_dir() && file.ends_with("engine.cfg")) { + confirm = false; + } + file = dir->get_next(); + } + dir->list_dir_end(); + } + memdelete(dir); + } + if (confirm) { + multi_scan_ask->get_ok()->disconnect("pressed", this, "_scan_multiple_folders"); + multi_scan_ask->get_ok()->connect("pressed", this, "_scan_multiple_folders", varray(folders)); + multi_scan_ask->set_text(vformat(TTR("You are about the scan %s folders for existing Godot projects. Do you confirm?"), folders.size())); + multi_scan_ask->popup_centered_minsize(); + } else { + _scan_multiple_folders(folders); } } - if (!import_project_file && p_files.size() > 0) { - scan_dir->set_current_dir(p_files[0]); - scan_dir->popup_centered_ratio(); +} + +void ProjectManager::_scan_multiple_folders(StringArray p_files) +{ + for (int i = 0; i < p_files.size(); i++) { + _scan_begin(p_files.get(i)); } } @@ -1136,6 +1170,7 @@ void ProjectManager::_bind_methods() { ObjectTypeDB::bind_method("_favorite_pressed",&ProjectManager::_favorite_pressed); ObjectTypeDB::bind_method("_install_project",&ProjectManager::_install_project); ObjectTypeDB::bind_method("_files_dropped",&ProjectManager::_files_dropped); + ObjectTypeDB::bind_method(_MD("_scan_multiple_folders", "files"),&ProjectManager::_scan_multiple_folders); } @@ -1332,8 +1367,13 @@ ProjectManager::ProjectManager() { multi_run_ask = memnew( ConfirmationDialog ); multi_run_ask->get_ok()->set_text(TTR("Run")); multi_run_ask->get_ok()->connect("pressed", this, "_run_project_confirm"); - + gui_base->add_child(multi_run_ask); + + multi_scan_ask = memnew( ConfirmationDialog ); + multi_scan_ask->get_ok()->set_text(TTR("Scan")); + + gui_base->add_child(multi_scan_ask); OS::get_singleton()->set_low_processor_usage_mode(true); diff --git a/tools/editor/project_manager.h b/tools/editor/project_manager.h index da570339059..46f7aea3a50 100644 --- a/tools/editor/project_manager.h +++ b/tools/editor/project_manager.h @@ -55,6 +55,7 @@ class ProjectManager : public Control { ConfirmationDialog *erase_ask; ConfirmationDialog *multi_open_ask; ConfirmationDialog *multi_run_ask; + ConfirmationDialog *multi_scan_ask; NewProjectDialog *npdialog; ScrollContainer *scroll; VBoxContainer *scroll_childs; @@ -93,6 +94,7 @@ class ProjectManager : public Control { void _unhandled_input(const InputEvent& p_ev); void _favorite_pressed(Node *p_hb); void _files_dropped(StringArray p_files, int p_screen); + void _scan_multiple_folders(StringArray p_files); protected: From 7b165e8ac27c8c6f979bf6e2da32a9a58836da08 Mon Sep 17 00:00:00 2001 From: Zher Huei Lee Date: Tue, 2 Aug 2016 08:01:51 +0100 Subject: [PATCH 61/63] Added texture mipmaps and filtering to DynamicFont --- scene/resources/dynamic_font.cpp | 80 +++++++++++++++++++++++++++++--- scene/resources/dynamic_font.h | 18 +++++-- 2 files changed, 88 insertions(+), 10 deletions(-) diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp index 67587a8f8ba..0c25bde7a97 100644 --- a/scene/resources/dynamic_font.cpp +++ b/scene/resources/dynamic_font.cpp @@ -32,7 +32,7 @@ -Ref DynamicFontData::_get_dynamic_font_at_size(int p_size) { +Ref DynamicFontData::_get_dynamic_font_at_size(int p_size, uint32_t p_texture_flags) { if (size_cache.has(p_size)) { @@ -48,6 +48,7 @@ Ref DynamicFontData::_get_dynamic_font_at_size(int p_size) { size_cache[p_size]=dfas.ptr(); + dfas->texture_flags=p_texture_flags; dfas->size=p_size; dfas->_load(); @@ -270,6 +271,15 @@ Size2 DynamicFontAtSize::get_char_size(CharType p_char,CharType p_next,const Vec return ret; } +void DynamicFontAtSize::set_texture_flags(uint32_t p_flags){ + + texture_flags=p_flags; + for(int i=0;i &tex = textures[i].texture; + if (!tex.is_null()) + tex->set_flags(p_flags); + } +} float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2& p_pos, CharType p_char,CharType p_next,const Color& p_modulate,const Vector >& p_fallbacks) const { @@ -555,7 +565,7 @@ void DynamicFontAtSize::_update_char(CharType p_char) { if (tex.texture.is_null()) { tex.texture.instance(); - tex.texture->create_from_image(img,Texture::FLAG_VIDEO_SURFACE); + tex.texture->create_from_image(img,Texture::FLAG_VIDEO_SURFACE|texture_flags); } else { tex.texture->set_data(img); //update } @@ -595,6 +605,7 @@ DynamicFontAtSize::DynamicFontAtSize() { ascent=1; descent=1; linegap=1; + texture_flags=0; } DynamicFontAtSize::~DynamicFontAtSize(){ @@ -613,7 +624,7 @@ void DynamicFont::set_font_data(const Ref& p_data) { data=p_data; if (data.is_valid()) - data_at_size=data->_get_dynamic_font_at_size(size); + data_at_size=data->_get_dynamic_font_at_size(size,texture_flags); else data_at_size=Ref(); @@ -634,19 +645,64 @@ void DynamicFont::set_size(int p_size){ ERR_FAIL_COND(p_size<1); if (!data.is_valid()) return; - data_at_size=data->_get_dynamic_font_at_size(size); + data_at_size=data->_get_dynamic_font_at_size(size,texture_flags); for(int i=0;i_get_dynamic_font_at_size(size); + fallback_data_at_size[i]=fallbacks[i]->_get_dynamic_font_at_size(size,texture_flags); } emit_changed(); _change_notify(); } + int DynamicFont::get_size() const{ return size; } +void DynamicFont::_update_texture_flags(){ + + texture_flags = 0; + if (use_mipmaps) + texture_flags|=Texture::FLAG_MIPMAPS; + if (use_filter) + texture_flags|=Texture::FLAG_FILTER; + if (!data.is_valid()) + return; + data_at_size->set_texture_flags(texture_flags); + for(int i=0;iset_texture_flags(texture_flags); + } + + emit_changed(); + _change_notify(); +} + +bool DynamicFont::get_use_mipmaps() const{ + + return use_mipmaps; +} + +void DynamicFont::set_use_mipmaps(bool p_enable){ + + if (use_mipmaps==p_enable) + return; + use_mipmaps=p_enable; + _update_texture_flags(); +} + +bool DynamicFont::get_use_filter() const{ + + return use_filter; +} + +void DynamicFont::set_use_filter(bool p_enable){ + + if (use_filter==p_enable) + return; + use_filter=p_enable; + _update_texture_flags(); +} + float DynamicFont::get_height() const{ if (!data_at_size.is_valid()) @@ -699,7 +755,7 @@ void DynamicFont::set_fallback(int p_idx,const Ref& p_data) { ERR_FAIL_COND(p_data.is_null()); ERR_FAIL_INDEX(p_idx,fallbacks.size()); fallbacks[p_idx]=p_data; - fallback_data_at_size[p_idx]=fallbacks[p_idx]->_get_dynamic_font_at_size(size); + fallback_data_at_size[p_idx]=fallbacks[p_idx]->_get_dynamic_font_at_size(size,texture_flags); } @@ -707,7 +763,7 @@ void DynamicFont::add_fallback(const Ref& p_data) { ERR_FAIL_COND(p_data.is_null()); fallbacks.push_back(p_data); - fallback_data_at_size.push_back(fallbacks[fallbacks.size()-1]->_get_dynamic_font_at_size(size)); //const.. + fallback_data_at_size.push_back(fallbacks[fallbacks.size()-1]->_get_dynamic_font_at_size(size,texture_flags)); //const.. _change_notify(); emit_changed(); @@ -794,6 +850,11 @@ void DynamicFont::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_size","data"),&DynamicFont::set_size); ObjectTypeDB::bind_method(_MD("get_size"),&DynamicFont::get_size); + ObjectTypeDB::bind_method(_MD("set_use_mipmaps","enable"),&DynamicFont::set_use_mipmaps); + ObjectTypeDB::bind_method(_MD("get_use_mipmaps"),&DynamicFont::get_use_mipmaps); + ObjectTypeDB::bind_method(_MD("set_use_filter","enable"),&DynamicFont::set_use_filter); + ObjectTypeDB::bind_method(_MD("get_use_filter"),&DynamicFont::get_use_filter); + ObjectTypeDB::bind_method(_MD("add_fallback","data:DynamicFontData"),&DynamicFont::add_fallback); ObjectTypeDB::bind_method(_MD("set_fallback","idx","data:DynamicFontData"),&DynamicFont::set_fallback); ObjectTypeDB::bind_method(_MD("get_fallback:DynamicFontData","idx"),&DynamicFont::get_fallback); @@ -802,12 +863,17 @@ void DynamicFont::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT,"font/size"),_SCS("set_size"),_SCS("get_size")); + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"font/use_mipmaps"),_SCS("set_use_mipmaps"),_SCS("get_use_mipmaps")); + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"font/use_filter"),_SCS("set_use_filter"),_SCS("get_use_filter")); ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"font/font",PROPERTY_HINT_RESOURCE_TYPE,"DynamicFontData"),_SCS("set_font_data"),_SCS("get_font_data")); } DynamicFont::DynamicFont() { size=16; + use_mipmaps=false; + use_filter=false; + texture_flags=0; } DynamicFont::~DynamicFont() { diff --git a/scene/resources/dynamic_font.h b/scene/resources/dynamic_font.h index 9ad1b4edbfe..c43dcd37f94 100644 --- a/scene/resources/dynamic_font.h +++ b/scene/resources/dynamic_font.h @@ -59,7 +59,7 @@ class DynamicFontData : public Resource { friend class DynamicFont; - Ref _get_dynamic_font_at_size(int p_size); + Ref _get_dynamic_font_at_size(int p_size, uint32_t p_texture_flags=0); protected: static void _bind_methods(); @@ -90,6 +90,8 @@ class DynamicFontAtSize : public Reference { int linegap; int rect_margin; + uint32_t texture_flags; + bool valid; struct CharTexture { @@ -145,7 +147,7 @@ public: float draw_char(RID p_canvas_item, const Point2& p_pos, CharType p_char,CharType p_next,const Color& p_modulate,const Vector >& p_fallbacks) const; - + void set_texture_flags(uint32_t p_flags); DynamicFontAtSize(); ~DynamicFontAtSize(); @@ -157,7 +159,7 @@ class DynamicFont : public Font { OBJ_TYPE( DynamicFont, Font ); - Ref data; + Ref data; Ref data_at_size; Vector< Ref > fallbacks; @@ -166,9 +168,14 @@ class DynamicFont : public Font { int size; bool valid; + bool use_mipmaps; + bool use_filter; + uint32_t texture_flags; protected: + void _update_texture_flags(); + bool _set(const StringName& p_name, const Variant& p_value); bool _get(const StringName& p_name,Variant &r_ret) const; void _get_property_list( List *p_list) const; @@ -183,6 +190,11 @@ public: void set_size(int p_size); int get_size() const; + bool get_use_mipmaps() const; + void set_use_mipmaps(bool p_enable); + + bool get_use_filter() const; + void set_use_filter(bool p_enable); void add_fallback(const Ref& p_data); void set_fallback(int p_idx,const Ref& p_data); From af6ef01c692311410c084b0bf4f3fe2f4d46786d Mon Sep 17 00:00:00 2001 From: Zher Huei Lee Date: Tue, 2 Aug 2016 11:05:20 +0100 Subject: [PATCH 62/63] Added extra spacing support for DynamicFont Side effect is that label min-size will now take into account kerning. --- scene/gui/label.cpp | 4 +-- scene/resources/dynamic_font.cpp | 62 +++++++++++++++++++++++++++++--- scene/resources/dynamic_font.h | 18 ++++++++++ 3 files changed, 77 insertions(+), 7 deletions(-) diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index 4c025e92df1..ec89b7b6902 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -334,7 +334,7 @@ int Label::get_longest_line_width() const { } } else { - int char_width=font->get_char_size(current).width; + int char_width=font->get_char_size(current,text[i+1]).width; line_width+=char_width; } @@ -454,7 +454,7 @@ void Label::regenerate_word_cache() { word_pos=i; } - char_width=font->get_char_size(current).width; + char_width=font->get_char_size(current,text[i+1]).width; current_word_size+=char_width; line_width+=char_width; total_char_cache++; diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp index 0c25bde7a97..0a3355e818f 100644 --- a/scene/resources/dynamic_font.cpp +++ b/scene/resources/dynamic_font.cpp @@ -703,12 +703,43 @@ void DynamicFont::set_use_filter(bool p_enable){ _update_texture_flags(); } +int DynamicFont::get_spacing(int p_type) const{ + + if (p_type == SPACING_TOP){ + return spacing_top; + }else if (p_type == SPACING_BOTTOM){ + return spacing_bottom; + }else if (p_type == SPACING_CHAR){ + return spacing_char; + }else if (p_type == SPACING_SPACE){ + return spacing_space; + } + + return 0; +} + +void DynamicFont::set_spacing(int p_type, int p_value){ + + if (p_type == SPACING_TOP){ + spacing_top=p_value; + }else if (p_type == SPACING_BOTTOM){ + spacing_bottom=p_value; + }else if (p_type == SPACING_CHAR){ + spacing_char=p_value; + }else if (p_type == SPACING_SPACE){ + spacing_space=p_value; + } + + emit_changed(); + _change_notify(); +} + float DynamicFont::get_height() const{ if (!data_at_size.is_valid()) return 1; - return data_at_size->get_height(); + return data_at_size->get_height()+spacing_top+spacing_bottom; } float DynamicFont::get_ascent() const{ @@ -716,7 +747,7 @@ float DynamicFont::get_ascent() const{ if (!data_at_size.is_valid()) return 1; - return data_at_size->get_ascent(); + return data_at_size->get_ascent()+spacing_top; } float DynamicFont::get_descent() const{ @@ -724,7 +755,7 @@ float DynamicFont::get_descent() const{ if (!data_at_size.is_valid()) return 1; - return data_at_size->get_descent(); + return data_at_size->get_descent()+spacing_bottom; } @@ -733,7 +764,13 @@ Size2 DynamicFont::get_char_size(CharType p_char,CharType p_next) const{ if (!data_at_size.is_valid()) return Size2(1,1); - return data_at_size->get_char_size(p_char,p_next,fallback_data_at_size); + Size2 ret=data_at_size->get_char_size(p_char,p_next,fallback_data_at_size); + if (p_char==' ') + ret.width+=spacing_space+spacing_char; + else if (p_next) + ret.width+=spacing_char; + + return ret; } @@ -747,7 +784,7 @@ float DynamicFont::draw_char(RID p_canvas_item, const Point2& p_pos, CharType p_ if (!data_at_size.is_valid()) return 0; - return data_at_size->draw_char(p_canvas_item,p_pos,p_char,p_next,p_modulate,fallback_data_at_size); + return data_at_size->draw_char(p_canvas_item,p_pos,p_char,p_next,p_modulate,fallback_data_at_size)+spacing_char; } void DynamicFont::set_fallback(int p_idx,const Ref& p_data) { @@ -854,6 +891,8 @@ void DynamicFont::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_use_mipmaps"),&DynamicFont::get_use_mipmaps); ObjectTypeDB::bind_method(_MD("set_use_filter","enable"),&DynamicFont::set_use_filter); ObjectTypeDB::bind_method(_MD("get_use_filter"),&DynamicFont::get_use_filter); + ObjectTypeDB::bind_method(_MD("set_spacing","type","value"),&DynamicFont::set_spacing); + ObjectTypeDB::bind_method(_MD("get_spacing","type"),&DynamicFont::get_spacing); ObjectTypeDB::bind_method(_MD("add_fallback","data:DynamicFontData"),&DynamicFont::add_fallback); ObjectTypeDB::bind_method(_MD("set_fallback","idx","data:DynamicFontData"),&DynamicFont::set_fallback); @@ -863,14 +902,27 @@ void DynamicFont::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT,"font/size"),_SCS("set_size"),_SCS("get_size")); + ADD_PROPERTYINZ(PropertyInfo(Variant::INT,"extra_spacing/top"),_SCS("set_spacing"),_SCS("get_spacing"),SPACING_TOP); + ADD_PROPERTYINZ(PropertyInfo(Variant::INT,"extra_spacing/bottom"),_SCS("set_spacing"),_SCS("get_spacing"),SPACING_BOTTOM); + ADD_PROPERTYINZ(PropertyInfo(Variant::INT,"extra_spacing/char"),_SCS("set_spacing"),_SCS("get_spacing"),SPACING_CHAR); + ADD_PROPERTYINZ(PropertyInfo(Variant::INT,"extra_spacing/space"),_SCS("set_spacing"),_SCS("get_spacing"),SPACING_SPACE); ADD_PROPERTY(PropertyInfo(Variant::BOOL,"font/use_mipmaps"),_SCS("set_use_mipmaps"),_SCS("get_use_mipmaps")); ADD_PROPERTY(PropertyInfo(Variant::BOOL,"font/use_filter"),_SCS("set_use_filter"),_SCS("get_use_filter")); ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"font/font",PROPERTY_HINT_RESOURCE_TYPE,"DynamicFontData"),_SCS("set_font_data"),_SCS("get_font_data")); + + BIND_CONSTANT( SPACING_TOP ); + BIND_CONSTANT( SPACING_BOTTOM ); + BIND_CONSTANT( SPACING_CHAR ); + BIND_CONSTANT( SPACING_SPACE ); } DynamicFont::DynamicFont() { size=16; + spacing_top=0; + spacing_bottom=0; + spacing_char=0; + spacing_space=0; use_mipmaps=false; use_filter=false; texture_flags=0; diff --git a/scene/resources/dynamic_font.h b/scene/resources/dynamic_font.h index c43dcd37f94..899973f22f3 100644 --- a/scene/resources/dynamic_font.h +++ b/scene/resources/dynamic_font.h @@ -159,6 +159,17 @@ class DynamicFont : public Font { OBJ_TYPE( DynamicFont, Font ); +public: + + enum SpacingType{ + SPACING_TOP, + SPACING_BOTTOM, + SPACING_CHAR, + SPACING_SPACE + }; + +private: + Ref data; Ref data_at_size; @@ -168,6 +179,10 @@ class DynamicFont : public Font { int size; bool valid; + int spacing_top; + int spacing_bottom; + int spacing_char; + int spacing_space; bool use_mipmaps; bool use_filter; uint32_t texture_flags; @@ -196,6 +211,9 @@ public: bool get_use_filter() const; void set_use_filter(bool p_enable); + int get_spacing(int p_type) const; + void set_spacing(int p_type, int p_value); + void add_fallback(const Ref& p_data); void set_fallback(int p_idx,const Ref& p_data); int get_fallback_count() const; From 0de7860511fe56f06d039c51ff463c7a1146b7e1 Mon Sep 17 00:00:00 2001 From: Zher Huei Lee Date: Tue, 2 Aug 2016 15:00:32 +0100 Subject: [PATCH 63/63] DynamicFont caches now accounts for texture flags CacheID added for future-proofing --- scene/resources/dynamic_font.cpp | 110 +++++++++++++++---------------- scene/resources/dynamic_font.h | 26 +++++--- 2 files changed, 69 insertions(+), 67 deletions(-) diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp index 0a3355e818f..679c8a000c1 100644 --- a/scene/resources/dynamic_font.cpp +++ b/scene/resources/dynamic_font.cpp @@ -30,13 +30,22 @@ #include "dynamic_font.h" #include "os/file_access.h" +bool DynamicFontData::CacheID::operator< (CacheID right) const{ + + if (size DynamicFontData::_get_dynamic_font_at_size(CacheID p_id){ -Ref DynamicFontData::_get_dynamic_font_at_size(int p_size, uint32_t p_texture_flags) { - - - if (size_cache.has(p_size)) { - return Ref( size_cache[p_size] ); + if (size_cache.has(p_id)) { + return Ref( size_cache[p_id] ); } @@ -46,10 +55,8 @@ Ref DynamicFontData::_get_dynamic_font_at_size(int p_size, ui dfas->font=Ref( this ); - size_cache[p_size]=dfas.ptr(); - - dfas->texture_flags=p_texture_flags; - dfas->size=p_size; + size_cache[p_id]=dfas.ptr(); + dfas->id=p_id; dfas->_load(); return dfas; @@ -170,11 +177,16 @@ Error DynamicFontAtSize::_load() { ERR_FAIL_COND_V( error, ERR_INVALID_PARAMETER ); }*/ - error = FT_Set_Pixel_Sizes(face,0,size); + error = FT_Set_Pixel_Sizes(face,0,id.size); ascent=face->size->metrics.ascender>>6; descent=-face->size->metrics.descender>>6; linegap=0; + texture_flags=0; + if (id.mipmaps) + texture_flags|=Texture::FLAG_MIPMAPS; + if (id.filter) + texture_flags|=Texture::FLAG_FILTER; //print_line("ASCENT: "+itos(ascent)+" descent "+itos(descent)+" hinted: "+itos(face->face_flags&FT_FACE_FLAG_HINTER)); @@ -506,7 +518,7 @@ void DynamicFontAtSize::_update_char(CharType p_char) { tex_x = 0; tex_y = 0; - int texsize = MAX(size*8,256); + int texsize = MAX(id.size*8,256); if (mw>texsize) texsize=mw; //special case, adapt to it? if (mh>texsize) @@ -612,19 +624,32 @@ DynamicFontAtSize::~DynamicFontAtSize(){ if (valid) { FT_Done_FreeType( library ); - font->size_cache.erase(size); + font->size_cache.erase(id); } } ///////////////////////// +void DynamicFont::_reload_cache(){ + + ERR_FAIL_COND(cache_id.size<1); + if (!data.is_valid()) + return; + data_at_size=data->_get_dynamic_font_at_size(cache_id); + for (int i=0;i_get_dynamic_font_at_size(cache_id); + } + + emit_changed(); + _change_notify(); +} void DynamicFont::set_font_data(const Ref& p_data) { data=p_data; if (data.is_valid()) - data_at_size=data->_get_dynamic_font_at_size(size,texture_flags); + data_at_size=data->_get_dynamic_font_at_size(cache_id); else data_at_size=Ref(); @@ -639,68 +664,41 @@ Ref DynamicFont::get_font_data() const{ void DynamicFont::set_size(int p_size){ - if (size==p_size) + if (cache_id.size==p_size) return; - size=p_size; - ERR_FAIL_COND(p_size<1); - if (!data.is_valid()) - return; - data_at_size=data->_get_dynamic_font_at_size(size,texture_flags); - for(int i=0;i_get_dynamic_font_at_size(size,texture_flags); - } - - emit_changed(); - _change_notify(); + cache_id.size=p_size; + _reload_cache(); } int DynamicFont::get_size() const{ - return size; -} - -void DynamicFont::_update_texture_flags(){ - - texture_flags = 0; - if (use_mipmaps) - texture_flags|=Texture::FLAG_MIPMAPS; - if (use_filter) - texture_flags|=Texture::FLAG_FILTER; - if (!data.is_valid()) - return; - data_at_size->set_texture_flags(texture_flags); - for(int i=0;iset_texture_flags(texture_flags); - } - - emit_changed(); - _change_notify(); + return cache_id.size; } bool DynamicFont::get_use_mipmaps() const{ - return use_mipmaps; + return cache_id.mipmaps; } void DynamicFont::set_use_mipmaps(bool p_enable){ - if (use_mipmaps==p_enable) + if (cache_id.mipmaps==p_enable) return; - use_mipmaps=p_enable; - _update_texture_flags(); + cache_id.mipmaps=p_enable; + _reload_cache(); } bool DynamicFont::get_use_filter() const{ - return use_filter; + return cache_id.filter; } void DynamicFont::set_use_filter(bool p_enable){ - if (use_filter==p_enable) + if (cache_id.filter==p_enable) return; - use_filter=p_enable; - _update_texture_flags(); + cache_id.filter=p_enable; + _reload_cache(); } int DynamicFont::get_spacing(int p_type) const{ @@ -792,7 +790,7 @@ void DynamicFont::set_fallback(int p_idx,const Ref& p_data) { ERR_FAIL_COND(p_data.is_null()); ERR_FAIL_INDEX(p_idx,fallbacks.size()); fallbacks[p_idx]=p_data; - fallback_data_at_size[p_idx]=fallbacks[p_idx]->_get_dynamic_font_at_size(size,texture_flags); + fallback_data_at_size[p_idx]=fallbacks[p_idx]->_get_dynamic_font_at_size(cache_id); } @@ -800,7 +798,7 @@ void DynamicFont::add_fallback(const Ref& p_data) { ERR_FAIL_COND(p_data.is_null()); fallbacks.push_back(p_data); - fallback_data_at_size.push_back(fallbacks[fallbacks.size()-1]->_get_dynamic_font_at_size(size,texture_flags)); //const.. + fallback_data_at_size.push_back(fallbacks[fallbacks.size()-1]->_get_dynamic_font_at_size(cache_id)); //const.. _change_notify(); emit_changed(); @@ -918,14 +916,10 @@ void DynamicFont::_bind_methods() { DynamicFont::DynamicFont() { - size=16; spacing_top=0; spacing_bottom=0; spacing_char=0; spacing_space=0; - use_mipmaps=false; - use_filter=false; - texture_flags=0; } DynamicFont::~DynamicFont() { diff --git a/scene/resources/dynamic_font.h b/scene/resources/dynamic_font.h index 899973f22f3..4ae58ab0dd5 100644 --- a/scene/resources/dynamic_font.h +++ b/scene/resources/dynamic_font.h @@ -45,21 +45,32 @@ class DynamicFontData : public Resource { OBJ_TYPE(DynamicFontData,Resource); +public: + struct CacheID{ + + int size; + bool mipmaps; + bool filter; + + bool operator< (CacheID right) const; + CacheID() { size=16; mipmaps=false; filter=false; } + }; + +private: const uint8_t *font_mem; int font_mem_size; bool force_autohinter; String font_path; - Map size_cache; + Map size_cache; friend class DynamicFontAtSize; friend class DynamicFont; - - Ref _get_dynamic_font_at_size(int p_size, uint32_t p_texture_flags=0); + Ref _get_dynamic_font_at_size(CacheID p_cache); protected: static void _bind_methods(); @@ -126,7 +137,7 @@ class DynamicFontAtSize : public Reference { friend class DynamicFontData; Ref font; - int size; + DynamicFontData::CacheID id; @@ -177,19 +188,16 @@ private: Vector< Ref > fallback_data_at_size; - int size; + DynamicFontData::CacheID cache_id; bool valid; int spacing_top; int spacing_bottom; int spacing_char; int spacing_space; - bool use_mipmaps; - bool use_filter; - uint32_t texture_flags; protected: - void _update_texture_flags(); + void _reload_cache(); bool _set(const StringName& p_name, const Variant& p_value); bool _get(const StringName& p_name,Variant &r_ret) const;