diff options
Diffstat (limited to 'core')
70 files changed, 4263 insertions, 118 deletions
diff --git a/core/array.cpp b/core/array.cpp index fef0fcbb40..1d283a14aa 100644 --- a/core/array.cpp +++ b/core/array.cpp @@ -155,6 +155,37 @@ int Array::find(const Variant& p_value) const { return _p->array.find(p_value); } +int Array::find_last(const Variant& p_value) const { + + if(_p->array.size() == 0) + return -1; + + for (int i=_p->array.size()-1; i>=0; i--) { + + if(_p->array[i] == p_value){ + return i; + }; + }; + + return -1; +} + +int Array::count(const Variant& p_value) const { + + if(_p->array.size() == 0) + return 0; + + int amount=0; + for (int i=0; i<_p->array.size(); i++) { + + if(_p->array[i] == p_value){ + amount++; + }; + }; + + return amount; +} + void Array::remove(int p_pos) { _p->array.remove(p_pos); diff --git a/core/array.h b/core/array.h index ecb91b69dc..9472a6dd21 100644 --- a/core/array.h +++ b/core/array.h @@ -72,6 +72,8 @@ public: void invert(); int find(const Variant& p_value) const; + int find_last(const Variant& p_value) const; + int count(const Variant& p_value) const; void erase(const Variant& p_value); diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index 1eb7f790a3..31c0c0e208 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -226,6 +226,11 @@ Size2 _OS::get_screen_size(int p_screen) const { return OS::get_singleton()->get_screen_size(p_screen); } +int _OS::get_screen_dpi(int p_screen) const { + + return OS::get_singleton()->get_screen_dpi(p_screen); +} + Point2 _OS::get_window_position() const { return OS::get_singleton()->get_window_position(); } @@ -431,6 +436,15 @@ Error _OS::set_thread_name(const String& p_name) { return Thread::set_name(p_name); }; +void _OS::set_use_vsync(bool p_enable) { + OS::get_singleton()->set_use_vsync(p_enable); +} + +bool _OS::is_vsnc_enabled() const { + + return OS::get_singleton()->is_vsnc_enabled(); +} + /* enum Weekday { @@ -500,9 +514,9 @@ void _OS::set_icon(const Image& p_icon) { } /** - * Get current datetime with consideration for utc and + * Get current datetime with consideration for utc and * dst - */ + */ Dictionary _OS::get_datetime(bool utc) const { Dictionary dated = get_date(utc); @@ -564,17 +578,17 @@ uint64_t _OS::get_unix_time_from_datetime(Dictionary datetime) const { // Get all time values from the dictionary, set to zero if it doesn't exist. // Risk incorrect calculation over throwing errors - unsigned int second = ((datetime.has(SECOND_KEY))? + unsigned int second = ((datetime.has(SECOND_KEY))? static_cast<unsigned int>(datetime[SECOND_KEY]): 0); - unsigned int minute = ((datetime.has(MINUTE_KEY))? + unsigned int minute = ((datetime.has(MINUTE_KEY))? static_cast<unsigned int>(datetime[MINUTE_KEY]): 0); - unsigned int hour = ((datetime.has(HOUR_KEY))? + unsigned int hour = ((datetime.has(HOUR_KEY))? static_cast<unsigned int>(datetime[HOUR_KEY]): 0); - unsigned int day = ((datetime.has(DAY_KEY))? + unsigned int day = ((datetime.has(DAY_KEY))? static_cast<unsigned int>(datetime[DAY_KEY]): 0); - unsigned int month = ((datetime.has(MONTH_KEY))? + unsigned int month = ((datetime.has(MONTH_KEY))? static_cast<unsigned int>(datetime[MONTH_KEY]) -1: 0); - unsigned int year = ((datetime.has(YEAR_KEY))? + unsigned int year = ((datetime.has(YEAR_KEY))? static_cast<unsigned int>(datetime[YEAR_KEY]):0); /// How many days come before each month (0-12) @@ -604,7 +618,7 @@ uint64_t _OS::get_unix_time_from_datetime(Dictionary datetime) const { ERR_FAIL_COND_V( day > MONTH_DAYS_TABLE[LEAPYEAR(year)][month], 0); // Calculate all the seconds from months past in this year - uint64_t SECONDS_FROM_MONTHS_PAST_THIS_YEAR = + uint64_t SECONDS_FROM_MONTHS_PAST_THIS_YEAR = DAYS_PAST_THIS_YEAR_TABLE[LEAPYEAR(year)][month] * SECONDS_PER_DAY; uint64_t SECONDS_FROM_YEARS_PAST = 0; @@ -614,13 +628,13 @@ uint64_t _OS::get_unix_time_from_datetime(Dictionary datetime) const { SECONDS_PER_DAY; } - uint64_t epoch = - second + - minute * SECONDS_PER_MINUTE + + uint64_t epoch = + second + + minute * SECONDS_PER_MINUTE + hour * SECONDS_PER_HOUR + // Subtract 1 from day, since the current day isn't over yet // and we cannot count all 24 hours. - (day-1) * SECONDS_PER_DAY + + (day-1) * SECONDS_PER_DAY + SECONDS_FROM_MONTHS_PAST_THIS_YEAR + SECONDS_FROM_YEARS_PAST; return epoch; @@ -631,7 +645,7 @@ uint64_t _OS::get_unix_time_from_datetime(Dictionary datetime) const { * Get a dictionary of time values when given epoch time * * Dictionary Time values will be a union if values from #get_time - * and #get_date dictionaries (with the exception of dst = + * and #get_date dictionaries (with the exception of dst = * day light standard time, as it cannot be determined from epoch) * * @param unix_time_val epoch time to convert @@ -660,14 +674,14 @@ Dictionary _OS::get_datetime_from_unix_time( uint64_t unix_time_val) const { time.hour = dayclock / 3600; /* day 0 was a thursday */ - date.weekday = static_cast<OS::Weekday>((dayno + 4) % 7); + date.weekday = static_cast<OS::Weekday>((dayno + 4) % 7); while (dayno >= YEARSIZE(year)) { dayno -= YEARSIZE(year); year++; } - date.year = year; + date.year = year; size_t imonth = 0; @@ -984,6 +998,7 @@ void _OS::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_current_screen","screen"),&_OS::set_current_screen); ObjectTypeDB::bind_method(_MD("get_screen_position","screen"),&_OS::get_screen_position,DEFVAL(0)); ObjectTypeDB::bind_method(_MD("get_screen_size","screen"),&_OS::get_screen_size,DEFVAL(0)); + ObjectTypeDB::bind_method(_MD("get_screen_dpi","screen"),&_OS::get_screen_dpi,DEFVAL(0)); ObjectTypeDB::bind_method(_MD("get_window_position"),&_OS::get_window_position); ObjectTypeDB::bind_method(_MD("set_window_position","position"),&_OS::set_window_position); ObjectTypeDB::bind_method(_MD("get_window_size"),&_OS::get_window_size); @@ -1104,6 +1119,8 @@ void _OS::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_thread_name","name"),&_OS::set_thread_name); + ObjectTypeDB::bind_method(_MD("set_use_vsync","enable"),&_OS::set_use_vsync); + ObjectTypeDB::bind_method(_MD("is_vsnc_enabled"),&_OS::is_vsnc_enabled); BIND_CONSTANT( DAY_SUNDAY ); BIND_CONSTANT( DAY_MONDAY ); @@ -1893,15 +1910,15 @@ void _Directory::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_drive","idx"),&_Directory::get_drive); ObjectTypeDB::bind_method(_MD("change_dir:Error","todir"),&_Directory::change_dir); ObjectTypeDB::bind_method(_MD("get_current_dir"),&_Directory::get_current_dir); - ObjectTypeDB::bind_method(_MD("make_dir:Error","name"),&_Directory::make_dir); - ObjectTypeDB::bind_method(_MD("make_dir_recursive:Error","name"),&_Directory::make_dir_recursive); - ObjectTypeDB::bind_method(_MD("file_exists","name"),&_Directory::file_exists); - ObjectTypeDB::bind_method(_MD("dir_exists","name"),&_Directory::dir_exists); + ObjectTypeDB::bind_method(_MD("make_dir:Error","path"),&_Directory::make_dir); + ObjectTypeDB::bind_method(_MD("make_dir_recursive:Error","path"),&_Directory::make_dir_recursive); + ObjectTypeDB::bind_method(_MD("file_exists","path"),&_Directory::file_exists); + ObjectTypeDB::bind_method(_MD("dir_exists","path"),&_Directory::dir_exists); // ObjectTypeDB::bind_method(_MD("get_modified_time","file"),&_Directory::get_modified_time); ObjectTypeDB::bind_method(_MD("get_space_left"),&_Directory::get_space_left); ObjectTypeDB::bind_method(_MD("copy:Error","from","to"),&_Directory::copy); ObjectTypeDB::bind_method(_MD("rename:Error","from","to"),&_Directory::rename); - ObjectTypeDB::bind_method(_MD("remove:Error","file"),&_Directory::remove); + ObjectTypeDB::bind_method(_MD("remove:Error","path"),&_Directory::remove); } diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index 0c768651ff..441927940d 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -117,6 +117,7 @@ public: virtual void set_current_screen(int p_screen); virtual Point2 get_screen_position(int p_screen=0) const; virtual Size2 get_screen_size(int p_screen=0) const; + virtual int get_screen_dpi(int p_screen=0) const; virtual Point2 get_window_position() const; virtual void set_window_position(const Point2& p_position); virtual Size2 get_window_size() const; @@ -281,6 +282,9 @@ public: Error set_thread_name(const String& p_name); + void set_use_vsync(bool p_enable); + bool is_vsnc_enabled() const; + static _OS *get_singleton() { return singleton; } _OS(); diff --git a/core/command_queue_mt.h b/core/command_queue_mt.h index b1e0066c35..409543bf25 100644 --- a/core/command_queue_mt.h +++ b/core/command_queue_mt.h @@ -152,6 +152,23 @@ class CommandQueueMT { virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6,p7); } }; + template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class P7,class P8> + struct Command8 : public CommandBase { + + T*instance; + M method; + typename GetSimpleTypeT<P1>::type_t p1; + typename GetSimpleTypeT<P2>::type_t p2; + typename GetSimpleTypeT<P3>::type_t p3; + typename GetSimpleTypeT<P4>::type_t p4; + typename GetSimpleTypeT<P5>::type_t p5; + typename GetSimpleTypeT<P6>::type_t p6; + typename GetSimpleTypeT<P7>::type_t p7; + typename GetSimpleTypeT<P8>::type_t p8; + + virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6,p7,p8); } + }; + /* comands that return */ template<class T,class M,class R> @@ -270,6 +287,25 @@ class CommandQueueMT { virtual void call() { *ret = (instance->*method)(p1,p2,p3,p4,p5,p6,p7); sync->sem->post(); sync->in_use=false; ; } }; + template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class P7,class P8,class R> + struct CommandRet8 : public CommandBase { + + T*instance; + M method; + typename GetSimpleTypeT<P1>::type_t p1; + typename GetSimpleTypeT<P2>::type_t p2; + typename GetSimpleTypeT<P3>::type_t p3; + typename GetSimpleTypeT<P4>::type_t p4; + typename GetSimpleTypeT<P5>::type_t p5; + typename GetSimpleTypeT<P6>::type_t p6; + typename GetSimpleTypeT<P7>::type_t p7; + typename GetSimpleTypeT<P8>::type_t p8; + R* ret; + SyncSemaphore *sync; + + virtual void call() { *ret = (instance->*method)(p1,p2,p3,p4,p5,p6,p7,p8); sync->sem->post(); sync->in_use=false; ; } + }; + /** commands that don't return but sync */ /* comands that return */ @@ -390,6 +426,25 @@ class CommandQueueMT { virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6,p7); sync->sem->post(); sync->in_use=false; ; } }; + template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class P7,class P8> + struct CommandSync8 : public CommandBase { + + T*instance; + M method; + typename GetSimpleTypeT<P1>::type_t p1; + typename GetSimpleTypeT<P2>::type_t p2; + typename GetSimpleTypeT<P3>::type_t p3; + typename GetSimpleTypeT<P4>::type_t p4; + typename GetSimpleTypeT<P5>::type_t p5; + typename GetSimpleTypeT<P6>::type_t p6; + typename GetSimpleTypeT<P7>::type_t p7; + typename GetSimpleTypeT<P8>::type_t p8; + + SyncSemaphore *sync; + + virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6,p7,p8); sync->sem->post(); sync->in_use=false; ; } + }; + /***** BASE *******/ enum { @@ -639,6 +694,27 @@ public: if (sync) sync->post(); } + + template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7,class P8> + void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8 ) { + + Command8<T,M,P1,P2,P3,P4,P5,P6,P7,P8> * cmd = allocate_and_lock< Command8<T,M,P1,P2,P3,P4,P5,P6,P7,P8> >(); + + cmd->instance=p_instance; + cmd->method=p_method; + cmd->p1=p1; + cmd->p2=p2; + cmd->p3=p3; + cmd->p4=p4; + cmd->p5=p5; + cmd->p6=p6; + cmd->p7=p7; + cmd->p8=p8; + + unlock(); + + if (sync) sync->post(); + } /*** PUSH AND RET COMMANDS ***/ @@ -806,6 +882,31 @@ public: ss->sem->wait(); } + template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6,class P7,class P8,class R> + void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6,P7 p7,P8 p8, R* r_ret ) { + + CommandRet8<T,M,P1,P2,P3,P4,P5,P6,P7,P8,R> * cmd = allocate_and_lock< CommandRet8<T,M,P1,P2,P3,P4,P5,P6,P7,P8,R> >(); + + cmd->instance=p_instance; + cmd->method=p_method; + cmd->p1=p1; + cmd->p2=p2; + cmd->p3=p3; + cmd->p4=p4; + cmd->p5=p5; + cmd->p6=p6; + cmd->p7=p7; + cmd->p8=p8; + cmd->ret=r_ret; + SyncSemaphore *ss=_alloc_sync_sem(); + cmd->sync=ss; + + unlock(); + + if (sync) sync->post(); + ss->sem->wait(); + } + template<class T, class M> void push_and_sync( T * p_instance, M p_method) { @@ -971,6 +1072,31 @@ public: ss->sem->wait(); } + template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6,class P7,class P8> + void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6,P7 p7,P8 p8) { + + CommandSync8<T,M,P1,P2,P3,P4,P5,P6,P7,P8> * cmd = allocate_and_lock< CommandSync8<T,M,P1,P2,P3,P4,P5,P6,P7,P8> >(); + + cmd->instance=p_instance; + cmd->method=p_method; + cmd->p1=p1; + cmd->p2=p2; + cmd->p3=p3; + cmd->p4=p4; + cmd->p5=p5; + cmd->p6=p6; + cmd->p7=p7; + cmd->p8=p8; + + SyncSemaphore *ss=_alloc_sync_sem(); + cmd->sync=ss; + + unlock(); + + if (sync) sync->post(); + ss->sem->wait(); + } + void wait_and_flush_one() { ERR_FAIL_COND(!sync); sync->wait(); diff --git a/core/dictionary.cpp b/core/dictionary.cpp index a013c21b29..6204a87054 100644 --- a/core/dictionary.cpp +++ b/core/dictionary.cpp @@ -110,6 +110,16 @@ bool Dictionary::has(const Variant& p_key) const { return _p->variant_map.has(p_key); } + +bool Dictionary::has_all(const Array& p_keys) const { + for (int i=0;i<p_keys.size();i++) { + if( !has(p_keys[i]) ) { + return false; + } + } + return true; +} + void Dictionary::erase(const Variant& p_key) { _copy_on_write(); _p->variant_map.erase(p_key); @@ -189,6 +199,18 @@ Array Dictionary::keys() const { } +Array Dictionary::values() const { + + Array varr; + varr.resize(size()); + const Variant *key=NULL; + int i=0; + while((key=next(key))){ + varr[i++] = _p->variant_map[*key]; + } + return varr; +} + const Variant* Dictionary::next(const Variant* p_key) const { return _p->variant_map.next(p_key); @@ -240,5 +262,3 @@ Dictionary::~Dictionary() { _unref(); } - - diff --git a/core/dictionary.h b/core/dictionary.h index 145e7e5c84..ae79fab9c3 100644 --- a/core/dictionary.h +++ b/core/dictionary.h @@ -69,6 +69,8 @@ public: bool is_shared() const; bool has(const Variant& p_key) const; + bool has_all(const Array& p_keys) const; + void erase(const Variant& p_key); bool operator==(const Dictionary& p_dictionary) const; @@ -79,6 +81,7 @@ public: const Variant* next(const Variant* p_key=NULL) const; Array keys() const; + Array values() const; Dictionary(const Dictionary& p_from); Dictionary(bool p_shared=false); diff --git a/core/dvector.h b/core/dvector.h index fbb1fc4824..a5519ed604 100644 --- a/core/dvector.h +++ b/core/dvector.h @@ -285,6 +285,7 @@ public: Error resize(int p_size); + void invert(); void operator=(const DVector& p_dvector) { reference(p_dvector); } DVector() {} @@ -424,6 +425,18 @@ Error DVector<T>::resize(int p_size) { return OK; } +template<class T> +void DVector<T>::invert() { + T temp; + Write w = write(); + int s = size(); + int half_s = s/2; + for(int i=0;i<half_s;i++) { + temp = w[i]; + w[i] = w[s-i-1]; + w[s-i-1] = temp; + } +} #endif diff --git a/core/global_constants.cpp b/core/global_constants.cpp index 130fca1b2a..63764383ff 100644 --- a/core/global_constants.cpp +++ b/core/global_constants.cpp @@ -476,10 +476,23 @@ static _GlobalConstant _global_constants[]={ BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_STORAGE ), - BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_STORAGE ), BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_EDITOR ), BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_NETWORK ), + + BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_EDITOR_HELPER ), + BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_CHECKABLE ), + BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_CHECKED ), + BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_INTERNATIONALIZED ), + BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_BUNDLE ), + BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_CATEGORY ), + BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_STORE_IF_NONZERO ), + BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_STORE_IF_NONONE ), + BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_NO_INSTANCE_STATE ), + BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_RESTART_IF_CHANGED ), + BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_DEFAULT ), + BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_DEFAULT_INTL ), + BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_NOEDITOR ), BIND_GLOBAL_CONSTANT( METHOD_FLAG_NORMAL ), BIND_GLOBAL_CONSTANT( METHOD_FLAG_EDITOR ), diff --git a/core/globals.cpp b/core/globals.cpp index c0c1171ae6..9e7b357d73 100644 --- a/core/globals.cpp +++ b/core/globals.cpp @@ -54,7 +54,7 @@ String Globals::localize_path(const String& p_path) const { if (resource_path=="") return p_path; //not initialied yet - if (p_path.find(":/") != -1) + if (p_path.begins_with("res://") || p_path.begins_with("user://")) return p_path.simplify_path(); @@ -82,6 +82,8 @@ String Globals::localize_path(const String& p_path) const { if (sep == -1) { return "res://"+path; }; + + String parent = path.substr(0, sep); String plocal = localize_path(parent); @@ -1526,6 +1528,7 @@ Globals::Globals() { custom_prop_info["render/thread_model"]=PropertyInfo(Variant::INT,"render/thread_model",PROPERTY_HINT_ENUM,"Single-Unsafe,Single-Safe,Multi-Threaded"); custom_prop_info["physics_2d/thread_model"]=PropertyInfo(Variant::INT,"physics_2d/thread_model",PROPERTY_HINT_ENUM,"Single-Unsafe,Single-Safe,Multi-Threaded"); + set("debug/profiler_max_functions",16384); using_datapack=false; } diff --git a/core/helper/value_evaluator.h b/core/helper/value_evaluator.h new file mode 100644 index 0000000000..a03602bc61 --- /dev/null +++ b/core/helper/value_evaluator.h @@ -0,0 +1,43 @@ +/*************************************************************************/ +/* value_evaluator.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef VALUE_EVALUATOR_H +#define VALUE_EVALUATOR_H + +#include "core/object.h" + +class ValueEvaluator : public Object { + + OBJ_TYPE(ValueEvaluator, Object); +public: + virtual double eval(const String& p_text) { + return p_text.to_double(); + } +}; + +#endif // VALUE_EVALUATOR_H diff --git a/core/hq2x.cpp b/core/hq2x.cpp new file mode 100644 index 0000000000..6495c77b2a --- /dev/null +++ b/core/hq2x.cpp @@ -0,0 +1,2636 @@ +/* + * Copyright 2016 Bruno Ribeiro + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include "hq2x.h" +#include "math_funcs.h" + + +static const uint32_t AMASK = 0xFF000000; +static const uint32_t YMASK = 0x00FF0000; +static const uint32_t UMASK = 0x0000FF00; +static const uint32_t VMASK = 0x000000FF; + +_FORCE_INLINE_ static uint32_t ARGBtoAYUV( + uint32_t value ) +{ + uint32_t A, R, G, B, Y, U, V; +//todo big endian check + A = value >> 24; + R = (value >> 16) & 0xFF; + G = (value >> 8) & 0xFF; + B = value & 0xFF; + + Y = Math::fast_ftoi( 0.299 * R + 0.587 * G + 0.114 * B); + U = Math::fast_ftoi(-0.169 * R - 0.331 * G + 0.5 * B) + 128; + V = Math::fast_ftoi( 0.5 * R - 0.419 * G - 0.081 * B) + 128; + return (A << 24) + (Y << 16) + (U << 8) + V; +} + + +/* + * Use this function for sharper images (good for cartoon style, used by DOSBOX) + */ + +_FORCE_INLINE_ static bool isDifferent( + uint32_t color1, + uint32_t color2, + uint32_t trY, + uint32_t trU, + uint32_t trV, + uint32_t trA ) +{ + color1 = ARGBtoAYUV(color1); + color2 = ARGBtoAYUV(color2); + + uint32_t value; + + value = ((color1 & YMASK) - (color2 & YMASK)); + value = (value ^ (value >> 31)) - (value >> 31); + if (value > trY) return true; + + value = ((color1 & UMASK) - (color2 & UMASK)); + value = (value ^ (value >> 31)) - (value >> 31); + if (value > trU) return true; + + value = ((color1 & VMASK) - (color2 & VMASK)); + value = (value ^ (value >> 31)) - (value >> 31); + if (value > trV) return true; + + value = ((color1 & AMASK) - (color2 & AMASK)); + value = (value ^ (value >> 31)) - (value >> 31); + if (value > trA) return true; + + return false; + +} + + + +#define MASK_RB 0x00FF00FF +#define MASK_G 0x0000FF00 +#define MASK_A 0xFF000000 + + +/** + * @brief Mixes two colors using the given weights. + */ +#define HQX_MIX_2(C0,C1,W0,W1) \ + ((((C0 & MASK_RB) * W0 + (C1 & MASK_RB) * W1) / (W0 + W1)) & MASK_RB) | \ + ((((C0 & MASK_G) * W0 + (C1 & MASK_G) * W1) / (W0 + W1)) & MASK_G) | \ + (((((C0 & MASK_A) >> 8) * W0 + ((C1 & MASK_A) >> 8) * W1) / (W0 + W1)) << 8) & MASK_A + +/** + * @brief Mixes three colors using the given weights. + */ +#define HQX_MIX_3(C0,C1,C2,W0,W1,W2) \ + ((((C0 & MASK_RB) * W0 + (C1 & MASK_RB) * W1 + (C2 & MASK_RB) * W2) / (W0 + W1 + W2)) & MASK_RB) | \ + ((((C0 & MASK_G) * W0 + (C1 & MASK_G) * W1 + (C2 & MASK_G) * W2) / (W0 + W1 + W2)) & MASK_G) | \ + (((((C0 & MASK_A) >> 8) * W0 + ((C1 & MASK_A) >> 8) * W1 + ((C2 & MASK_A) >> 8) * W2) / (W0 + W1 + W2)) << 8) & MASK_A + + +#define MIX_00_4 *output = w[4]; +#define MIX_00_MIX_00_4_0_3_1 *output = HQX_MIX_2(w[4],w[0],3U,1U); +#define MIX_00_4_3_3_1 *output = HQX_MIX_2(w[4],w[3],3U,1U); +#define MIX_00_4_1_3_1 *output = HQX_MIX_2(w[4],w[1],3U,1U); +#define MIX_00_3_1_1_1 *output = HQX_MIX_2(w[3],w[1],1U,1U); +#define MIX_00_4_3_1_2_1_1 *output = HQX_MIX_3(w[4],w[3],w[1],2U,1U,1U); +#define MIX_00_4_3_1_2_7_7 *output = HQX_MIX_3(w[4],w[3],w[1],2U,7U,7U); +#define MIX_00_4_0_1_2_1_1 *output = HQX_MIX_3(w[4],w[0],w[1],2U,1U,1U); +#define MIX_00_4_0_3_2_1_1 *output = HQX_MIX_3(w[4],w[0],w[3],2U,1U,1U); +#define MIX_00_4_1_3_5_2_1 *output = HQX_MIX_3(w[4],w[1],w[3],5U,2U,1U); +#define MIX_00_4_3_1_5_2_1 *output = HQX_MIX_3(w[4],w[3],w[1],5U,2U,1U); +#define MIX_00_4_3_1_6_1_1 *output = HQX_MIX_3(w[4],w[3],w[1],6U,1U,1U); +#define MIX_00_4_3_1_2_3_3 *output = HQX_MIX_3(w[4],w[3],w[1],2U,3U,3U); +#define MIX_00_MIX_00_4_0_3_10 *output = HQX_MIX_3(w[4],w[3],w[1],14U,1U,1U); + +#define MIX_01_4 *(output + 1) = w[4]; +#define MIX_01_4_2_3_1 *(output + 1) = HQX_MIX_2(w[4],w[2],3U,1U); +#define MIX_01_4_1_3_1 *(output + 1) = HQX_MIX_2(w[4],w[1],3U,1U); +#define MIX_01_1_4_3_1 *(output + 1) = HQX_MIX_2(w[1],w[4],3U,1U); +#define MIX_01_4_5_3_1 *(output + 1) = HQX_MIX_2(w[4],w[5],3U,1U); +#define MIX_01_4_1_7_1 *(output + 1) = HQX_MIX_2(w[4],w[1],7U,1U); +#define MIX_01_4_1_5_2_1_1 *(output + 1) = HQX_MIX_3(w[4],w[1],w[5],2U,1U,1U); +#define MIX_01_4_2_5_2_1_1 *(output + 1) = HQX_MIX_3(w[4],w[2],w[5],2U,1U,1U); +#define MIX_01_4_2_1_2_1_1 *(output + 1) = HQX_MIX_3(w[4],w[2],w[1],2U,1U,1U); +#define MIX_01_4_5_1_5_2_1 *(output + 1) = HQX_MIX_3(w[4],w[5],w[1],5U,2U,1U); +#define MIX_01_4_1_5_5_2_1 *(output + 1) = HQX_MIX_3(w[4],w[1],w[5],5U,2U,1U); +#define MIX_01_4_1_5_6_1_1 *(output + 1) = HQX_MIX_3(w[4],w[1],w[5],6U,1U,1U); +#define MIX_01_4_1_5_2_3_3 *(output + 1) = HQX_MIX_3(w[4],w[1],w[5],2U,3U,3U); +#define MIX_01_4_2_3_10 *(output + 1) = HQX_MIX_3(w[4],w[1],w[5],14U,1U,1U); + +#define MIX_02_4 *(output + 2) = w[4]; +#define MIX_02_4_2_3_1 *(output + 2) = HQX_MIX_2(w[4],w[2],3U,1U); +#define MIX_02_4_1_3_1 *(output + 2) = HQX_MIX_2(w[4],w[1],3U,1U); +#define MIX_02_4_5_3_1 *(output + 2) = HQX_MIX_2(w[4],w[5],3U,1U); +#define MIX_02_4_1_5_2_1_1 *(output + 2) = HQX_MIX_3(w[4],w[1],w[5],2U,1U,1U); +#define MIX_02_4_1_5_2_7_7 *(output + 2) = HQX_MIX_3(w[4],w[1],w[5],2U,7U,7U); +#define MIX_02_1_5_1_1 *(output + 2) = HQX_MIX_2(w[1],w[5],1U,1U); + +#define MIX_10_4 *(output + lineSize) = w[4]; +#define MIX_10_4_6_3_1 *(output + lineSize) = HQX_MIX_2(w[4],w[6],3U,1U); +#define MIX_10_4_7_3_1 *(output + lineSize) = HQX_MIX_2(w[4],w[7],3U,1U); +#define MIX_10_4_3_3_1 *(output + lineSize) = HQX_MIX_2(w[4],w[3],3U,1U); +#define MIX_10_4_7_3_2_1_1 *(output + lineSize) = HQX_MIX_3(w[4],w[7],w[3],2U,1U,1U); +#define MIX_10_4_6_3_2_1_1 *(output + lineSize) = HQX_MIX_3(w[4],w[6],w[3],2U,1U,1U); +#define MIX_10_4_6_7_2_1_1 *(output + lineSize) = HQX_MIX_3(w[4],w[6],w[7],2U,1U,1U); +#define MIX_10_4_3_7_5_2_1 *(output + lineSize) = HQX_MIX_3(w[4],w[3],w[7],5U,2U,1U); +#define MIX_10_4_7_3_5_2_1 *(output + lineSize) = HQX_MIX_3(w[4],w[7],w[3],5U,2U,1U); +#define MIX_10_4_7_3_6_1_1 *(output + lineSize) = HQX_MIX_3(w[4],w[7],w[3],6U,1U,1U); +#define MIX_10_4_7_3_2_3_3 *(output + lineSize) = HQX_MIX_3(w[4],w[7],w[3],2U,3U,3U); +#define MIX_10_4_6_3_10 *(output + lineSize) = HQX_MIX_3(w[4],w[7],w[3],14U,1U,1U); +#define MIX_10_4_3_7_1 *(output + lineSize) = HQX_MIX_2(w[4],w[3],7U,1U); +#define MIX_10_3_4_3_1 *(output + lineSize) = HQX_MIX_2(w[3],w[4],3U,1U); + +#define MIX_11_4 *(output + lineSize + 1) = w[4]; +#define MIX_11_4_8_3_1 *(output + lineSize + 1) = HQX_MIX_2(w[4],w[8],3U,1U); +#define MIX_11_4_5_3_1 *(output + lineSize + 1) = HQX_MIX_2(w[4],w[5],3U,1U); +#define MIX_11_4_7_3_1 *(output + lineSize + 1) = HQX_MIX_2(w[4],w[7],3U,1U); +#define MIX_11_4_5_7_2_1_1 *(output + lineSize + 1) = HQX_MIX_3(w[4],w[5],w[7],2U,1U,1U); +#define MIX_11_4_8_7_2_1_1 *(output + lineSize + 1) = HQX_MIX_3(w[4],w[8],w[7],2U,1U,1U); +#define MIX_11_4_8_5_2_1_1 *(output + lineSize + 1) = HQX_MIX_3(w[4],w[8],w[5],2U,1U,1U); +#define MIX_11_4_7_5_5_2_1 *(output + lineSize + 1) = HQX_MIX_3(w[4],w[7],w[5],5U,2U,1U); +#define MIX_11_4_5_7_5_2_1 *(output + lineSize + 1) = HQX_MIX_3(w[4],w[5],w[7],5U,2U,1U); +#define MIX_11_4_5_7_6_1_1 *(output + lineSize + 1) = HQX_MIX_3(w[4],w[5],w[7],6U,1U,1U); +#define MIX_11_4_5_7_2_3_3 *(output + lineSize + 1) = HQX_MIX_3(w[4],w[5],w[7],2U,3U,3U); +#define MIX_11_4_8_3_10 *(output + lineSize + 1) = HQX_MIX_3(w[4],w[5],w[7],14U,1U,1U); + +#define MIX_12_4 *(output + lineSize + 2) = w[4]; +#define MIX_12_4_5_3_1 *(output + lineSize + 2) = HQX_MIX_2(w[4],w[5],3U,1U); +#define MIX_12_4_5_7_1 *(output + lineSize + 2) = HQX_MIX_2(w[4],w[5],7U,1U); +#define MIX_12_5_4_3_1 *(output + lineSize + 2) = HQX_MIX_2(w[5],w[4],3U,1U); + +#define MIX_20_4 *(output + lineSize + lineSize) = w[4]; +#define MIX_20_4_6_3_1 *(output + lineSize + lineSize) = HQX_MIX_2(w[4],w[6],3U,1U); +#define MIX_20_4_7_3_1 *(output + lineSize + lineSize) = HQX_MIX_2(w[4],w[7],3U,1U); +#define MIX_20_4_3_3_1 *(output + lineSize + lineSize) = HQX_MIX_2(w[4],w[3],3U,1U); +#define MIX_20_4_7_3_2_1_1 *(output + lineSize + lineSize) = HQX_MIX_3(w[4],w[7],w[3],2U,1U,1U); +#define MIX_20_4_7_3_2_7_7 *(output + lineSize + lineSize) = HQX_MIX_3(w[4],w[7],w[3],2U,7U,7U); +#define MIX_20_7_3_1_1 *(output + lineSize + lineSize) = HQX_MIX_2(w[7],w[3],1U,1U); + +#define MIX_21_4 *(output + lineSize + lineSize + 1) = w[4]; +#define MIX_21_4_7_3_1 *(output + lineSize + lineSize + 1) = HQX_MIX_2(w[4],w[7],3U,1U); +#define MIX_21_4_7_7_1 *(output + lineSize + lineSize + 1) = HQX_MIX_2(w[4],w[7],7U,1U); +#define MIX_21_7_4_3_1 *(output + lineSize + lineSize + 1) = HQX_MIX_2(w[7],w[4],3U,1U); + +#define MIX_22_4 *(output + lineSize + lineSize + 2) = w[4]; +#define MIX_22_4_8_3_1 *(output + lineSize + lineSize + 2) = HQX_MIX_2(w[4],w[8],3U,1U); +#define MIX_22_4_7_3_1 *(output + lineSize + lineSize + 2) = HQX_MIX_2(w[4],w[7],3U,1U); +#define MIX_22_4_5_3_1 *(output + lineSize + lineSize + 2) = HQX_MIX_2(w[4],w[5],3U,1U); +#define MIX_22_4_5_7_2_1_1 *(output + lineSize + lineSize + 2) = HQX_MIX_3(w[4],w[5],w[7],2U,1U,1U); +#define MIX_22_4_5_7_2_7_7 *(output + lineSize + lineSize + 2) = HQX_MIX_3(w[4],w[5],w[7],2U,7U,7U); +#define MIX_22_5_7_1_1 *(output + lineSize + lineSize + 2) = HQX_MIX_2(w[5],w[7],1U,1U); + + + +uint32_t *hq2x_resize( + const uint32_t *image, + uint32_t width, + uint32_t height, + uint32_t *output, + uint32_t trY, + uint32_t trU, + uint32_t trV, + uint32_t trA, + bool wrapX, + bool wrapY ) +{ + int lineSize = width * 2; + + int previous, next; + uint32_t w[9]; + + trY <<= 16; + trU <<= 8; + trA <<= 24; + + // iterates between the lines + for (uint32_t row = 0; row < height; row++) + { + /* + * Note: this function uses a 3x3 sliding window over the original image. + * + * +----+----+----+ + * | | | | + * | w0 | w1 | w2 | + * +----+----+----+ + * | | | | + * | w3 | w4 | w5 | + * +----+----+----+ + * | | | | + * | w6 | w7 | w8 | + * +----+----+----+ + */ + + // adjusts the previous and next line pointers + if (row > 0) + previous = -width; + else + { + if (wrapY) + previous = width * (height - 1); + else + previous = 0; + } + if (row < height - 1) + next = width; + else + { + if (wrapY) + next = -(width * (height - 1)); + else + next = 0; + } + + // iterates between the columns + for (uint32_t col = 0; col < width; col++) + { + w[1] = *(image + previous); + w[4] = *image; + w[7] = *(image + next); + + if (col > 0) + { + w[0] = *(image + previous - 1); + w[3] = *(image - 1); + w[6] = *(image + next - 1); + } + else + { + if (wrapX) + { + w[0] = *(image + previous + width - 1); + w[3] = *(image + width - 1); + w[6] = *(image + next + width - 1); + } + else + { + w[0] = w[1]; + w[3] = w[4]; + w[6] = w[7]; + } + } + + if (col < width - 1) + { + w[2] = *(image + previous + 1); + w[5] = *(image + 1); + w[8] = *(image + next + 1); + } + else + { + if (wrapX) + { + w[2] = *(image + previous - width + 1); + w[5] = *(image - width + 1); + w[8] = *(image + next - width + 1); + } + else + { + w[2] = w[1]; + w[5] = w[4]; + w[8] = w[7]; + } + } + + int pattern = 0; + + // computes the pattern to be used considering the neighbor pixels + for (int k = 0, flag = 1; k < 9; k++) + { + // ignores the central pixel + if (k == 4) continue; + + if (w[k] != w[4]) + if (isDifferent(w[4], w[k], trY, trU, trV, trA)) pattern |= flag; + flag <<= 1; + } + + switch (pattern) + { + case 0: + case 1: + case 4: + case 32: + case 128: + case 5: + case 132: + case 160: + case 33: + case 129: + case 36: + case 133: + case 164: + case 161: + case 37: + case 165: + MIX_00_4_3_1_2_1_1 + MIX_01_4_1_5_2_1_1 + MIX_10_4_7_3_2_1_1 + MIX_11_4_5_7_2_1_1 + break; + case 2: + case 34: + case 130: + case 162: + MIX_00_4_0_3_2_1_1 + MIX_01_4_2_5_2_1_1 + MIX_10_4_7_3_2_1_1 + MIX_11_4_5_7_2_1_1 + break; + case 16: + case 17: + case 48: + case 49: + MIX_00_4_3_1_2_1_1 + MIX_01_4_2_1_2_1_1 + MIX_10_4_7_3_2_1_1 + MIX_11_4_8_7_2_1_1 + break; + case 64: + case 65: + case 68: + case 69: + MIX_00_4_3_1_2_1_1 + MIX_01_4_1_5_2_1_1 + MIX_10_4_6_3_2_1_1 + MIX_11_4_8_5_2_1_1 + break; + case 8: + case 12: + case 136: + case 140: + MIX_00_4_0_1_2_1_1 + MIX_01_4_1_5_2_1_1 + MIX_10_4_6_7_2_1_1 + MIX_11_4_5_7_2_1_1 + break; + case 3: + case 35: + case 131: + case 163: + MIX_00_4_3_3_1 + MIX_01_4_2_5_2_1_1 + MIX_10_4_7_3_2_1_1 + MIX_11_4_5_7_2_1_1 + break; + case 6: + case 38: + case 134: + case 166: + MIX_00_4_0_3_2_1_1 + MIX_01_4_5_3_1 + MIX_10_4_7_3_2_1_1 + MIX_11_4_5_7_2_1_1 + break; + case 20: + case 21: + case 52: + case 53: + MIX_00_4_3_1_2_1_1 + MIX_01_4_1_3_1 + MIX_10_4_7_3_2_1_1 + MIX_11_4_8_7_2_1_1 + break; + case 144: + case 145: + case 176: + case 177: + MIX_00_4_3_1_2_1_1 + MIX_01_4_2_1_2_1_1 + MIX_10_4_7_3_2_1_1 + MIX_11_4_7_3_1 + break; + case 192: + case 193: + case 196: + case 197: + MIX_00_4_3_1_2_1_1 + MIX_01_4_1_5_2_1_1 + MIX_10_4_6_3_2_1_1 + MIX_11_4_5_3_1 + break; + case 96: + case 97: + case 100: + case 101: + MIX_00_4_3_1_2_1_1 + MIX_01_4_1_5_2_1_1 + MIX_10_4_3_3_1 + MIX_11_4_8_5_2_1_1 + break; + case 40: + case 44: + case 168: + case 172: + MIX_00_4_0_1_2_1_1 + MIX_01_4_1_5_2_1_1 + MIX_10_4_7_3_1 + MIX_11_4_5_7_2_1_1 + break; + case 9: + case 13: + case 137: + case 141: + MIX_00_4_1_3_1 + MIX_01_4_1_5_2_1_1 + MIX_10_4_6_7_2_1_1 + MIX_11_4_5_7_2_1_1 + break; + case 18: + case 50: + MIX_00_4_0_3_2_1_1 + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4_2_3_1 + } + else + { + MIX_01_4_1_5_2_1_1 + } + MIX_10_4_7_3_2_1_1 + MIX_11_4_8_7_2_1_1 + break; + case 80: + case 81: + MIX_00_4_3_1_2_1_1 + MIX_01_4_2_1_2_1_1 + MIX_10_4_6_3_2_1_1 + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4_8_3_1 + } + else + { + MIX_11_4_5_7_2_1_1 + } + break; + case 72: + case 76: + MIX_00_4_0_1_2_1_1 + MIX_01_4_1_5_2_1_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4_6_3_1 + } + else + { + MIX_10_4_7_3_2_1_1 + } + MIX_11_4_8_5_2_1_1 + break; + case 10: + case 138: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_MIX_00_4_0_3_1 + } + else + { + MIX_00_4_3_1_2_1_1 + } + MIX_01_4_2_5_2_1_1 + MIX_10_4_6_7_2_1_1 + MIX_11_4_5_7_2_1_1 + break; + case 66: + MIX_00_4_0_3_2_1_1 + MIX_01_4_2_5_2_1_1 + MIX_10_4_6_3_2_1_1 + MIX_11_4_8_5_2_1_1 + break; + case 24: + MIX_00_4_0_1_2_1_1 + MIX_01_4_2_1_2_1_1 + MIX_10_4_6_7_2_1_1 + MIX_11_4_8_7_2_1_1 + break; + case 7: + case 39: + case 135: + MIX_00_4_3_3_1 + MIX_01_4_5_3_1 + MIX_10_4_7_3_2_1_1 + MIX_11_4_5_7_2_1_1 + break; + case 148: + case 149: + case 180: + MIX_00_4_3_1_2_1_1 + MIX_01_4_1_3_1 + MIX_10_4_7_3_2_1_1 + MIX_11_4_7_3_1 + break; + case 224: + case 228: + case 225: + MIX_00_4_3_1_2_1_1 + MIX_01_4_1_5_2_1_1 + MIX_10_4_3_3_1 + MIX_11_4_5_3_1 + break; + case 41: + case 169: + case 45: + MIX_00_4_1_3_1 + MIX_01_4_1_5_2_1_1 + MIX_10_4_7_3_1 + MIX_11_4_5_7_2_1_1 + break; + case 22: + case 54: + MIX_00_4_0_3_2_1_1 + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4 + } + else + { + MIX_01_4_1_5_2_1_1 + } + MIX_10_4_7_3_2_1_1 + MIX_11_4_8_7_2_1_1 + break; + case 208: + case 209: + MIX_00_4_3_1_2_1_1 + MIX_01_4_2_1_2_1_1 + MIX_10_4_6_3_2_1_1 + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4 + } + else + { + MIX_11_4_5_7_2_1_1 + } + break; + case 104: + case 108: + MIX_00_4_0_1_2_1_1 + MIX_01_4_1_5_2_1_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4 + } + else + { + MIX_10_4_7_3_2_1_1 + } + MIX_11_4_8_5_2_1_1 + break; + case 11: + case 139: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + } + else + { + MIX_00_4_3_1_2_1_1 + } + MIX_01_4_2_5_2_1_1 + MIX_10_4_6_7_2_1_1 + MIX_11_4_5_7_2_1_1 + break; + case 19: + case 51: + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_00_4_3_3_1 + MIX_01_4_2_3_1 + } + else + { + MIX_00_4_1_3_5_2_1 + MIX_01_4_1_5_2_3_3 + } + MIX_10_4_7_3_2_1_1 + MIX_11_4_8_7_2_1_1 + break; + case 146: + case 178: + MIX_00_4_0_3_2_1_1 + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4_2_3_1 + MIX_11_4_7_3_1 + } + else + { + MIX_01_4_1_5_2_3_3 + MIX_11_4_5_7_5_2_1 + } + MIX_10_4_7_3_2_1_1 + break; + case 84: + case 85: + MIX_00_4_3_1_2_1_1 + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_01_4_1_3_1 + MIX_11_4_8_3_1 + } + else + { + MIX_01_4_5_1_5_2_1 + MIX_11_4_5_7_2_3_3 + } + MIX_10_4_6_3_2_1_1 + break; + case 112: + case 113: + MIX_00_4_3_1_2_1_1 + MIX_01_4_2_1_2_1_1 + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_10_4_3_3_1 + MIX_11_4_8_3_1 + } + else + { + MIX_10_4_7_3_5_2_1 + MIX_11_4_5_7_2_3_3 + } + break; + case 200: + case 204: + MIX_00_4_0_1_2_1_1 + MIX_01_4_1_5_2_1_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4_6_3_1 + MIX_11_4_5_3_1 + } + else + { + MIX_10_4_7_3_2_3_3 + MIX_11_4_7_5_5_2_1 + } + break; + case 73: + case 77: + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_00_4_1_3_1 + MIX_10_4_6_3_1 + } + else + { + MIX_00_4_3_1_5_2_1 + MIX_10_4_7_3_2_3_3 + } + MIX_01_4_1_5_2_1_1 + MIX_11_4_8_5_2_1_1 + break; + case 42: + case 170: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_MIX_00_4_0_3_1 + MIX_10_4_7_3_1 + } + else + { + MIX_00_4_3_1_2_3_3 + MIX_10_4_3_7_5_2_1 + } + MIX_01_4_2_5_2_1_1 + MIX_11_4_5_7_2_1_1 + break; + case 14: + case 142: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_MIX_00_4_0_3_1 + MIX_01_4_5_3_1 + } + else + { + MIX_00_4_3_1_2_3_3 + MIX_01_4_1_5_5_2_1 + } + MIX_10_4_6_7_2_1_1 + MIX_11_4_5_7_2_1_1 + break; + case 67: + MIX_00_4_3_3_1 + MIX_01_4_2_5_2_1_1 + MIX_10_4_6_3_2_1_1 + MIX_11_4_8_5_2_1_1 + break; + case 70: + MIX_00_4_0_3_2_1_1 + MIX_01_4_5_3_1 + MIX_10_4_6_3_2_1_1 + MIX_11_4_8_5_2_1_1 + break; + case 28: + MIX_00_4_0_1_2_1_1 + MIX_01_4_1_3_1 + MIX_10_4_6_7_2_1_1 + MIX_11_4_8_7_2_1_1 + break; + case 152: + MIX_00_4_0_1_2_1_1 + MIX_01_4_2_1_2_1_1 + MIX_10_4_6_7_2_1_1 + MIX_11_4_7_3_1 + break; + case 194: + MIX_00_4_0_3_2_1_1 + MIX_01_4_2_5_2_1_1 + MIX_10_4_6_3_2_1_1 + MIX_11_4_5_3_1 + break; + case 98: + MIX_00_4_0_3_2_1_1 + MIX_01_4_2_5_2_1_1 + MIX_10_4_3_3_1 + MIX_11_4_8_5_2_1_1 + break; + case 56: + MIX_00_4_0_1_2_1_1 + MIX_01_4_2_1_2_1_1 + MIX_10_4_7_3_1 + MIX_11_4_8_7_2_1_1 + break; + case 25: + MIX_00_4_1_3_1 + MIX_01_4_2_1_2_1_1 + MIX_10_4_6_7_2_1_1 + MIX_11_4_8_7_2_1_1 + break; + case 26: + case 31: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + } + else + { + MIX_00_4_3_1_2_1_1 + } + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4 + } + else + { + MIX_01_4_1_5_2_1_1 + } + MIX_10_4_6_7_2_1_1 + MIX_11_4_8_7_2_1_1 + break; + case 82: + case 214: + MIX_00_4_0_3_2_1_1 + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4 + } + else + { + MIX_01_4_1_5_2_1_1 + } + MIX_10_4_6_3_2_1_1 + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4 + } + else + { + MIX_11_4_5_7_2_1_1 + } + break; + case 88: + case 248: + MIX_00_4_0_1_2_1_1 + MIX_01_4_2_1_2_1_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4 + } + else + { + MIX_10_4_7_3_2_1_1 + } + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4 + } + else + { + MIX_11_4_5_7_2_1_1 + } + break; + case 74: + case 107: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + } + else + { + MIX_00_4_3_1_2_1_1 + } + MIX_01_4_2_5_2_1_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4 + } + else + { + MIX_10_4_7_3_2_1_1 + } + MIX_11_4_8_5_2_1_1 + break; + case 27: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + } + else + { + MIX_00_4_3_1_2_1_1 + } + MIX_01_4_2_3_1 + MIX_10_4_6_7_2_1_1 + MIX_11_4_8_7_2_1_1 + break; + case 86: + MIX_00_4_0_3_2_1_1 + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4 + } + else + { + MIX_01_4_1_5_2_1_1 + } + MIX_10_4_6_3_2_1_1 + MIX_11_4_8_3_1 + break; + case 216: + MIX_00_4_0_1_2_1_1 + MIX_01_4_2_1_2_1_1 + MIX_10_4_6_3_1 + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4 + } + else + { + MIX_11_4_5_7_2_1_1 + } + break; + case 106: + MIX_00_MIX_00_4_0_3_1 + MIX_01_4_2_5_2_1_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4 + } + else + { + MIX_10_4_7_3_2_1_1 + } + MIX_11_4_8_5_2_1_1 + break; + case 30: + MIX_00_MIX_00_4_0_3_1 + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4 + } + else + { + MIX_01_4_1_5_2_1_1 + } + MIX_10_4_6_7_2_1_1 + MIX_11_4_8_7_2_1_1 + break; + case 210: + MIX_00_4_0_3_2_1_1 + MIX_01_4_2_3_1 + MIX_10_4_6_3_2_1_1 + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4 + } + else + { + MIX_11_4_5_7_2_1_1 + } + break; + case 120: + MIX_00_4_0_1_2_1_1 + MIX_01_4_2_1_2_1_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4 + } + else + { + MIX_10_4_7_3_2_1_1 + } + MIX_11_4_8_3_1 + break; + case 75: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + } + else + { + MIX_00_4_3_1_2_1_1 + } + MIX_01_4_2_5_2_1_1 + MIX_10_4_6_3_1 + MIX_11_4_8_5_2_1_1 + break; + case 29: + MIX_00_4_1_3_1 + MIX_01_4_1_3_1 + MIX_10_4_6_7_2_1_1 + MIX_11_4_8_7_2_1_1 + break; + case 198: + MIX_00_4_0_3_2_1_1 + MIX_01_4_5_3_1 + MIX_10_4_6_3_2_1_1 + MIX_11_4_5_3_1 + break; + case 184: + MIX_00_4_0_1_2_1_1 + MIX_01_4_2_1_2_1_1 + MIX_10_4_7_3_1 + MIX_11_4_7_3_1 + break; + case 99: + MIX_00_4_3_3_1 + MIX_01_4_2_5_2_1_1 + MIX_10_4_3_3_1 + MIX_11_4_8_5_2_1_1 + break; + case 57: + MIX_00_4_1_3_1 + MIX_01_4_2_1_2_1_1 + MIX_10_4_7_3_1 + MIX_11_4_8_7_2_1_1 + break; + case 71: + MIX_00_4_3_3_1 + MIX_01_4_5_3_1 + MIX_10_4_6_3_2_1_1 + MIX_11_4_8_5_2_1_1 + break; + case 156: + MIX_00_4_0_1_2_1_1 + MIX_01_4_1_3_1 + MIX_10_4_6_7_2_1_1 + MIX_11_4_7_3_1 + break; + case 226: + MIX_00_4_0_3_2_1_1 + MIX_01_4_2_5_2_1_1 + MIX_10_4_3_3_1 + MIX_11_4_5_3_1 + break; + case 60: + MIX_00_4_0_1_2_1_1 + MIX_01_4_1_3_1 + MIX_10_4_7_3_1 + MIX_11_4_8_7_2_1_1 + break; + case 195: + MIX_00_4_3_3_1 + MIX_01_4_2_5_2_1_1 + MIX_10_4_6_3_2_1_1 + MIX_11_4_5_3_1 + break; + case 102: + MIX_00_4_0_3_2_1_1 + MIX_01_4_5_3_1 + MIX_10_4_3_3_1 + MIX_11_4_8_5_2_1_1 + break; + case 153: + MIX_00_4_1_3_1 + MIX_01_4_2_1_2_1_1 + MIX_10_4_6_7_2_1_1 + MIX_11_4_7_3_1 + break; + case 58: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_MIX_00_4_0_3_1 + } + else + { + MIX_00_4_3_1_6_1_1 + } + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4_2_3_1 + } + else + { + MIX_01_4_1_5_6_1_1 + } + MIX_10_4_7_3_1 + MIX_11_4_8_7_2_1_1 + break; + case 83: + MIX_00_4_3_3_1 + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4_2_3_1 + } + else + { + MIX_01_4_1_5_6_1_1 + } + MIX_10_4_6_3_2_1_1 + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4_8_3_1 + } + else + { + MIX_11_4_5_7_6_1_1 + } + break; + case 92: + MIX_00_4_0_1_2_1_1 + MIX_01_4_1_3_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4_6_3_1 + } + else + { + MIX_10_4_7_3_6_1_1 + } + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4_8_3_1 + } + else + { + MIX_11_4_5_7_6_1_1 + } + break; + case 202: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_MIX_00_4_0_3_1 + } + else + { + MIX_00_4_3_1_6_1_1 + } + MIX_01_4_2_5_2_1_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4_6_3_1 + } + else + { + MIX_10_4_7_3_6_1_1 + } + MIX_11_4_5_3_1 + break; + case 78: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_MIX_00_4_0_3_1 + } + else + { + MIX_00_4_3_1_6_1_1 + } + MIX_01_4_5_3_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4_6_3_1 + } + else + { + MIX_10_4_7_3_6_1_1 + } + MIX_11_4_8_5_2_1_1 + break; + case 154: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_MIX_00_4_0_3_1 + } + else + { + MIX_00_4_3_1_6_1_1 + } + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4_2_3_1 + } + else + { + MIX_01_4_1_5_6_1_1 + } + MIX_10_4_6_7_2_1_1 + MIX_11_4_7_3_1 + break; + case 114: + MIX_00_4_0_3_2_1_1 + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4_2_3_1 + } + else + { + MIX_01_4_1_5_6_1_1 + } + MIX_10_4_3_3_1 + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4_8_3_1 + } + else + { + MIX_11_4_5_7_6_1_1 + } + break; + case 89: + MIX_00_4_1_3_1 + MIX_01_4_2_1_2_1_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4_6_3_1 + } + else + { + MIX_10_4_7_3_6_1_1 + } + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4_8_3_1 + } + else + { + MIX_11_4_5_7_6_1_1 + } + break; + case 90: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_MIX_00_4_0_3_1 + } + else + { + MIX_00_4_3_1_6_1_1 + } + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4_2_3_1 + } + else + { + MIX_01_4_1_5_6_1_1 + } + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4_6_3_1 + } + else + { + MIX_10_4_7_3_6_1_1 + } + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4_8_3_1 + } + else + { + MIX_11_4_5_7_6_1_1 + } + break; + case 55: + case 23: + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_00_4_3_3_1 + MIX_01_4 + } + else + { + MIX_00_4_1_3_5_2_1 + MIX_01_4_1_5_2_3_3 + } + MIX_10_4_7_3_2_1_1 + MIX_11_4_8_7_2_1_1 + break; + case 182: + case 150: + MIX_00_4_0_3_2_1_1 + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4 + MIX_11_4_7_3_1 + } + else + { + MIX_01_4_1_5_2_3_3 + MIX_11_4_5_7_5_2_1 + } + MIX_10_4_7_3_2_1_1 + break; + case 213: + case 212: + MIX_00_4_3_1_2_1_1 + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_01_4_1_3_1 + MIX_11_4 + } + else + { + MIX_01_4_5_1_5_2_1 + MIX_11_4_5_7_2_3_3 + } + MIX_10_4_6_3_2_1_1 + break; + case 241: + case 240: + MIX_00_4_3_1_2_1_1 + MIX_01_4_2_1_2_1_1 + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_10_4_3_3_1 + MIX_11_4 + } + else + { + MIX_10_4_7_3_5_2_1 + MIX_11_4_5_7_2_3_3 + } + break; + case 236: + case 232: + MIX_00_4_0_1_2_1_1 + MIX_01_4_1_5_2_1_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4 + MIX_11_4_5_3_1 + } + else + { + MIX_10_4_7_3_2_3_3 + MIX_11_4_7_5_5_2_1 + } + break; + case 109: + case 105: + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_00_4_1_3_1 + MIX_10_4 + } + else + { + MIX_00_4_3_1_5_2_1 + MIX_10_4_7_3_2_3_3 + } + MIX_01_4_1_5_2_1_1 + MIX_11_4_8_5_2_1_1 + break; + case 171: + case 43: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + MIX_10_4_7_3_1 + } + else + { + MIX_00_4_3_1_2_3_3 + MIX_10_4_3_7_5_2_1 + } + MIX_01_4_2_5_2_1_1 + MIX_11_4_5_7_2_1_1 + break; + case 143: + case 15: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + MIX_01_4_5_3_1 + } + else + { + MIX_00_4_3_1_2_3_3 + MIX_01_4_1_5_5_2_1 + } + MIX_10_4_6_7_2_1_1 + MIX_11_4_5_7_2_1_1 + break; + case 124: + MIX_00_4_0_1_2_1_1 + MIX_01_4_1_3_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4 + } + else + { + MIX_10_4_7_3_2_1_1 + } + MIX_11_4_8_3_1 + break; + case 203: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + } + else + { + MIX_00_4_3_1_2_1_1 + } + MIX_01_4_2_5_2_1_1 + MIX_10_4_6_3_1 + MIX_11_4_5_3_1 + break; + case 62: + MIX_00_MIX_00_4_0_3_1 + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4 + } + else + { + MIX_01_4_1_5_2_1_1 + } + MIX_10_4_7_3_1 + MIX_11_4_8_7_2_1_1 + break; + case 211: + MIX_00_4_3_3_1 + MIX_01_4_2_3_1 + MIX_10_4_6_3_2_1_1 + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4 + } + else + { + MIX_11_4_5_7_2_1_1 + } + break; + case 118: + MIX_00_4_0_3_2_1_1 + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4 + } + else + { + MIX_01_4_1_5_2_1_1 + } + MIX_10_4_3_3_1 + MIX_11_4_8_3_1 + break; + case 217: + MIX_00_4_1_3_1 + MIX_01_4_2_1_2_1_1 + MIX_10_4_6_3_1 + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4 + } + else + { + MIX_11_4_5_7_2_1_1 + } + break; + case 110: + MIX_00_MIX_00_4_0_3_1 + MIX_01_4_5_3_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4 + } + else + { + MIX_10_4_7_3_2_1_1 + } + MIX_11_4_8_5_2_1_1 + break; + case 155: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + } + else + { + MIX_00_4_3_1_2_1_1 + } + MIX_01_4_2_3_1 + MIX_10_4_6_7_2_1_1 + MIX_11_4_7_3_1 + break; + case 188: + MIX_00_4_0_1_2_1_1 + MIX_01_4_1_3_1 + MIX_10_4_7_3_1 + MIX_11_4_7_3_1 + break; + case 185: + MIX_00_4_1_3_1 + MIX_01_4_2_1_2_1_1 + MIX_10_4_7_3_1 + MIX_11_4_7_3_1 + break; + case 61: + MIX_00_4_1_3_1 + MIX_01_4_1_3_1 + MIX_10_4_7_3_1 + MIX_11_4_8_7_2_1_1 + break; + case 157: + MIX_00_4_1_3_1 + MIX_01_4_1_3_1 + MIX_10_4_6_7_2_1_1 + MIX_11_4_7_3_1 + break; + case 103: + MIX_00_4_3_3_1 + MIX_01_4_5_3_1 + MIX_10_4_3_3_1 + MIX_11_4_8_5_2_1_1 + break; + case 227: + MIX_00_4_3_3_1 + MIX_01_4_2_5_2_1_1 + MIX_10_4_3_3_1 + MIX_11_4_5_3_1 + break; + case 230: + MIX_00_4_0_3_2_1_1 + MIX_01_4_5_3_1 + MIX_10_4_3_3_1 + MIX_11_4_5_3_1 + break; + case 199: + MIX_00_4_3_3_1 + MIX_01_4_5_3_1 + MIX_10_4_6_3_2_1_1 + MIX_11_4_5_3_1 + break; + case 220: + MIX_00_4_0_1_2_1_1 + MIX_01_4_1_3_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4_6_3_1 + } + else + { + MIX_10_4_7_3_6_1_1 + } + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4 + } + else + { + MIX_11_4_5_7_2_1_1 + } + break; + case 158: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_MIX_00_4_0_3_1 + } + else + { + MIX_00_4_3_1_6_1_1 + } + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4 + } + else + { + MIX_01_4_1_5_2_1_1 + } + MIX_10_4_6_7_2_1_1 + MIX_11_4_7_3_1 + break; + case 234: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_MIX_00_4_0_3_1 + } + else + { + MIX_00_4_3_1_6_1_1 + } + MIX_01_4_2_5_2_1_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4 + } + else + { + MIX_10_4_7_3_2_1_1 + } + MIX_11_4_5_3_1 + break; + case 242: + MIX_00_4_0_3_2_1_1 + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4_2_3_1 + } + else + { + MIX_01_4_1_5_6_1_1 + } + MIX_10_4_3_3_1 + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4 + } + else + { + MIX_11_4_5_7_2_1_1 + } + break; + case 59: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + } + else + { + MIX_00_4_3_1_2_1_1 + } + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4_2_3_1 + } + else + { + MIX_01_4_1_5_6_1_1 + } + MIX_10_4_7_3_1 + MIX_11_4_8_7_2_1_1 + break; + case 121: + MIX_00_4_1_3_1 + MIX_01_4_2_1_2_1_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4 + } + else + { + MIX_10_4_7_3_2_1_1 + } + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4_8_3_1 + } + else + { + MIX_11_4_5_7_6_1_1 + } + break; + case 87: + MIX_00_4_3_3_1 + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4 + } + else + { + MIX_01_4_1_5_2_1_1 + } + MIX_10_4_6_3_2_1_1 + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4_8_3_1 + } + else + { + MIX_11_4_5_7_6_1_1 + } + break; + case 79: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + } + else + { + MIX_00_4_3_1_2_1_1 + } + MIX_01_4_5_3_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4_6_3_1 + } + else + { + MIX_10_4_7_3_6_1_1 + } + MIX_11_4_8_5_2_1_1 + break; + case 122: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_MIX_00_4_0_3_1 + } + else + { + MIX_00_4_3_1_6_1_1 + } + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4_2_3_1 + } + else + { + MIX_01_4_1_5_6_1_1 + } + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4 + } + else + { + MIX_10_4_7_3_2_1_1 + } + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4_8_3_1 + } + else + { + MIX_11_4_5_7_6_1_1 + } + break; + case 94: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_MIX_00_4_0_3_1 + } + else + { + MIX_00_4_3_1_6_1_1 + } + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4 + } + else + { + MIX_01_4_1_5_2_1_1 + } + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4_6_3_1 + } + else + { + MIX_10_4_7_3_6_1_1 + } + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4_8_3_1 + } + else + { + MIX_11_4_5_7_6_1_1 + } + break; + case 218: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_MIX_00_4_0_3_1 + } + else + { + MIX_00_4_3_1_6_1_1 + } + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4_2_3_1 + } + else + { + MIX_01_4_1_5_6_1_1 + } + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4_6_3_1 + } + else + { + MIX_10_4_7_3_6_1_1 + } + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4 + } + else + { + MIX_11_4_5_7_2_1_1 + } + break; + case 91: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + } + else + { + MIX_00_4_3_1_2_1_1 + } + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4_2_3_1 + } + else + { + MIX_01_4_1_5_6_1_1 + } + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4_6_3_1 + } + else + { + MIX_10_4_7_3_6_1_1 + } + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4_8_3_1 + } + else + { + MIX_11_4_5_7_6_1_1 + } + break; + case 229: + MIX_00_4_3_1_2_1_1 + MIX_01_4_1_5_2_1_1 + MIX_10_4_3_3_1 + MIX_11_4_5_3_1 + break; + case 167: + MIX_00_4_3_3_1 + MIX_01_4_5_3_1 + MIX_10_4_7_3_2_1_1 + MIX_11_4_5_7_2_1_1 + break; + case 173: + MIX_00_4_1_3_1 + MIX_01_4_1_5_2_1_1 + MIX_10_4_7_3_1 + MIX_11_4_5_7_2_1_1 + break; + case 181: + MIX_00_4_3_1_2_1_1 + MIX_01_4_1_3_1 + MIX_10_4_7_3_2_1_1 + MIX_11_4_7_3_1 + break; + case 186: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_MIX_00_4_0_3_1 + } + else + { + MIX_00_4_3_1_6_1_1 + } + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4_2_3_1 + } + else + { + MIX_01_4_1_5_6_1_1 + } + MIX_10_4_7_3_1 + MIX_11_4_7_3_1 + break; + case 115: + MIX_00_4_3_3_1 + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4_2_3_1 + } + else + { + MIX_01_4_1_5_6_1_1 + } + MIX_10_4_3_3_1 + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4_8_3_1 + } + else + { + MIX_11_4_5_7_6_1_1 + } + break; + case 93: + MIX_00_4_1_3_1 + MIX_01_4_1_3_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4_6_3_1 + } + else + { + MIX_10_4_7_3_6_1_1 + } + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4_8_3_1 + } + else + { + MIX_11_4_5_7_6_1_1 + } + break; + case 206: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_MIX_00_4_0_3_1 + } + else + { + MIX_00_4_3_1_6_1_1 + } + MIX_01_4_5_3_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4_6_3_1 + } + else + { + MIX_10_4_7_3_6_1_1 + } + MIX_11_4_5_3_1 + break; + case 205: + case 201: + MIX_00_4_1_3_1 + MIX_01_4_1_5_2_1_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4_6_3_1 + } + else + { + MIX_10_4_7_3_6_1_1 + } + MIX_11_4_5_3_1 + break; + case 174: + case 46: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_MIX_00_4_0_3_1 + } + else + { + MIX_00_4_3_1_6_1_1 + } + MIX_01_4_5_3_1 + MIX_10_4_7_3_1 + MIX_11_4_5_7_2_1_1 + break; + case 179: + case 147: + MIX_00_4_3_3_1 + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4_2_3_1 + } + else + { + MIX_01_4_1_5_6_1_1 + } + MIX_10_4_7_3_2_1_1 + MIX_11_4_7_3_1 + break; + case 117: + case 116: + MIX_00_4_3_1_2_1_1 + MIX_01_4_1_3_1 + MIX_10_4_3_3_1 + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4_8_3_1 + } + else + { + MIX_11_4_5_7_6_1_1 + } + break; + case 189: + MIX_00_4_1_3_1 + MIX_01_4_1_3_1 + MIX_10_4_7_3_1 + MIX_11_4_7_3_1 + break; + case 231: + MIX_00_4_3_3_1 + MIX_01_4_5_3_1 + MIX_10_4_3_3_1 + MIX_11_4_5_3_1 + break; + case 126: + MIX_00_MIX_00_4_0_3_1 + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4 + } + else + { + MIX_01_4_1_5_2_1_1 + } + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4 + } + else + { + MIX_10_4_7_3_2_1_1 + } + MIX_11_4_8_3_1 + break; + case 219: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + } + else + { + MIX_00_4_3_1_2_1_1 + } + MIX_01_4_2_3_1 + MIX_10_4_6_3_1 + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4 + } + else + { + MIX_11_4_5_7_2_1_1 + } + break; + case 125: + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_00_4_1_3_1 + MIX_10_4 + } + else + { + MIX_00_4_3_1_5_2_1 + MIX_10_4_7_3_2_3_3 + } + MIX_01_4_1_3_1 + MIX_11_4_8_3_1 + break; + case 221: + MIX_00_4_1_3_1 + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_01_4_1_3_1 + MIX_11_4 + } + else + { + MIX_01_4_5_1_5_2_1 + MIX_11_4_5_7_2_3_3 + } + MIX_10_4_6_3_1 + break; + case 207: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + MIX_01_4_5_3_1 + } + else + { + MIX_00_4_3_1_2_3_3 + MIX_01_4_1_5_5_2_1 + } + MIX_10_4_6_3_1 + MIX_11_4_5_3_1 + break; + case 238: + MIX_00_MIX_00_4_0_3_1 + MIX_01_4_5_3_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4 + MIX_11_4_5_3_1 + } + else + { + MIX_10_4_7_3_2_3_3 + MIX_11_4_7_5_5_2_1 + } + break; + case 190: + MIX_00_MIX_00_4_0_3_1 + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4 + MIX_11_4_7_3_1 + } + else + { + MIX_01_4_1_5_2_3_3 + MIX_11_4_5_7_5_2_1 + } + MIX_10_4_7_3_1 + break; + case 187: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + MIX_10_4_7_3_1 + } + else + { + MIX_00_4_3_1_2_3_3 + MIX_10_4_3_7_5_2_1 + } + MIX_01_4_2_3_1 + MIX_11_4_7_3_1 + break; + case 243: + MIX_00_4_3_3_1 + MIX_01_4_2_3_1 + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_10_4_3_3_1 + MIX_11_4 + } + else + { + MIX_10_4_7_3_5_2_1 + MIX_11_4_5_7_2_3_3 + } + break; + case 119: + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_00_4_3_3_1 + MIX_01_4 + } + else + { + MIX_00_4_1_3_5_2_1 + MIX_01_4_1_5_2_3_3 + } + MIX_10_4_3_3_1 + MIX_11_4_8_3_1 + break; + case 237: + case 233: + MIX_00_4_1_3_1 + MIX_01_4_1_5_2_1_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4 + } + else + { + MIX_10_4_6_3_10 + } + MIX_11_4_5_3_1 + break; + case 175: + case 47: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + } + else + { + MIX_00_MIX_00_4_0_3_10 + } + MIX_01_4_5_3_1 + MIX_10_4_7_3_1 + MIX_11_4_5_7_2_1_1 + break; + case 183: + case 151: + MIX_00_4_3_3_1 + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4 + } + else + { + MIX_01_4_2_3_10 + } + MIX_10_4_7_3_2_1_1 + MIX_11_4_7_3_1 + break; + case 245: + case 244: + MIX_00_4_3_1_2_1_1 + MIX_01_4_1_3_1 + MIX_10_4_3_3_1 + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4 + } + else + { + MIX_11_4_8_3_10 + } + break; + case 250: + MIX_00_MIX_00_4_0_3_1 + MIX_01_4_2_3_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4 + } + else + { + MIX_10_4_7_3_2_1_1 + } + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4 + } + else + { + MIX_11_4_5_7_2_1_1 + } + break; + case 123: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + } + else + { + MIX_00_4_3_1_2_1_1 + } + MIX_01_4_2_3_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4 + } + else + { + MIX_10_4_7_3_2_1_1 + } + MIX_11_4_8_3_1 + break; + case 95: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + } + else + { + MIX_00_4_3_1_2_1_1 + } + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4 + } + else + { + MIX_01_4_1_5_2_1_1 + } + MIX_10_4_6_3_1 + MIX_11_4_8_3_1 + break; + case 222: + MIX_00_MIX_00_4_0_3_1 + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4 + } + else + { + MIX_01_4_1_5_2_1_1 + } + MIX_10_4_6_3_1 + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4 + } + else + { + MIX_11_4_5_7_2_1_1 + } + break; + case 252: + MIX_00_4_0_1_2_1_1 + MIX_01_4_1_3_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4 + } + else + { + MIX_10_4_7_3_2_1_1 + } + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4 + } + else + { + MIX_11_4_8_3_10 + } + break; + case 249: + MIX_00_4_1_3_1 + MIX_01_4_2_1_2_1_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4 + } + else + { + MIX_10_4_6_3_10 + } + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4 + } + else + { + MIX_11_4_5_7_2_1_1 + } + break; + case 235: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + } + else + { + MIX_00_4_3_1_2_1_1 + } + MIX_01_4_2_5_2_1_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4 + } + else + { + MIX_10_4_6_3_10 + } + MIX_11_4_5_3_1 + break; + case 111: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + } + else + { + MIX_00_MIX_00_4_0_3_10 + } + MIX_01_4_5_3_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4 + } + else + { + MIX_10_4_7_3_2_1_1 + } + MIX_11_4_8_5_2_1_1 + break; + case 63: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + } + else + { + MIX_00_MIX_00_4_0_3_10 + } + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4 + } + else + { + MIX_01_4_1_5_2_1_1 + } + MIX_10_4_7_3_1 + MIX_11_4_8_7_2_1_1 + break; + case 159: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + } + else + { + MIX_00_4_3_1_2_1_1 + } + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4 + } + else + { + MIX_01_4_2_3_10 + } + MIX_10_4_6_7_2_1_1 + MIX_11_4_7_3_1 + break; + case 215: + MIX_00_4_3_3_1 + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4 + } + else + { + MIX_01_4_2_3_10 + } + MIX_10_4_6_3_2_1_1 + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4 + } + else + { + MIX_11_4_5_7_2_1_1 + } + break; + case 246: + MIX_00_4_0_3_2_1_1 + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4 + } + else + { + MIX_01_4_1_5_2_1_1 + } + MIX_10_4_3_3_1 + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4 + } + else + { + MIX_11_4_8_3_10 + } + break; + case 254: + MIX_00_MIX_00_4_0_3_1 + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4 + } + else + { + MIX_01_4_1_5_2_1_1 + } + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4 + } + else + { + MIX_10_4_7_3_2_1_1 + } + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4 + } + else + { + MIX_11_4_8_3_10 + } + break; + case 253: + MIX_00_4_1_3_1 + MIX_01_4_1_3_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4 + } + else + { + MIX_10_4_6_3_10 + } + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4 + } + else + { + MIX_11_4_8_3_10 + } + break; + case 251: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + } + else + { + MIX_00_4_3_1_2_1_1 + } + MIX_01_4_2_3_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4 + } + else + { + MIX_10_4_6_3_10 + } + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4 + } + else + { + MIX_11_4_5_7_2_1_1 + } + break; + case 239: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + } + else + { + MIX_00_MIX_00_4_0_3_10 + } + MIX_01_4_5_3_1 + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4 + } + else + { + MIX_10_4_6_3_10 + } + MIX_11_4_5_3_1 + break; + case 127: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + } + else + { + MIX_00_MIX_00_4_0_3_10 + } + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4 + } + else + { + MIX_01_4_1_5_2_1_1 + } + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + { + MIX_10_4 + } + else + { + MIX_10_4_7_3_2_1_1 + } + MIX_11_4_8_3_1 + break; + case 191: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + } + else + { + MIX_00_MIX_00_4_0_3_10 + } + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4 + } + else + { + MIX_01_4_2_3_10 + } + MIX_10_4_7_3_1 + MIX_11_4_7_3_1 + break; + case 223: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + { + MIX_00_4 + } + else + { + MIX_00_4_3_1_2_1_1 + } + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4 + } + else + { + MIX_01_4_2_3_10 + } + MIX_10_4_6_3_1 + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4 + } + else + { + MIX_11_4_5_7_2_1_1 + } + break; + case 247: + MIX_00_4_3_3_1 + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + { + MIX_01_4 + } + else + { + MIX_01_4_2_3_10 + } + MIX_10_4_3_3_1 + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + { + MIX_11_4 + } + else + { + MIX_11_4_8_3_10 + } + break; + case 255: + if (isDifferent(w[3], w[1], trY, trU, trV, trA)) + MIX_00_4 + else + MIX_00_MIX_00_4_0_3_10 + + if (isDifferent(w[1], w[5], trY, trU, trV, trA)) + MIX_01_4 + else + MIX_01_4_2_3_10 + + if (isDifferent(w[7], w[3], trY, trU, trV, trA)) + MIX_10_4 + else + MIX_10_4_6_3_10 + + if (isDifferent(w[5], w[7], trY, trU, trV, trA)) + MIX_11_4 + else + MIX_11_4_8_3_10 + break; + } + image++; + output += 2; + } + output += lineSize; + } + + return output; +} diff --git a/core/hq2x.h b/core/hq2x.h new file mode 100644 index 0000000000..8f119d2a01 --- /dev/null +++ b/core/hq2x.h @@ -0,0 +1,19 @@ +#ifndef HQ2X_H +#define HQ2X_H + +#include "typedefs.h" + + +uint32_t *hq2x_resize( + const uint32_t *image, + uint32_t width, + uint32_t height, + uint32_t *output, + uint32_t trY = 0x30, + uint32_t trU = 0x07, + uint32_t trV = 0x06, + uint32_t trA = 0x50, + bool wrapX = false, + bool wrapY = false ); + +#endif // HQ2X_H diff --git a/core/image.cpp b/core/image.cpp index 52946bbb85..57496683ef 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -30,7 +30,7 @@ #include "hash_map.h" #include "core/io/image_loader.h" #include "core/os/copymem.h" - +#include "hq2x.h" #include "print_string.h" #include <stdio.h> @@ -901,6 +901,104 @@ static void _generate_po2_mipmap(const uint8_t* p_src, uint8_t* p_dst, uint32_t } +void Image::expand_x2_hq2x() { + + ERR_FAIL_COND(format>=FORMAT_INDEXED); + + Format current = format; + bool mipmaps=get_mipmaps(); + if (mipmaps) { + clear_mipmaps(); + } + + if (current!=FORMAT_RGBA) + convert(FORMAT_RGBA); + + DVector<uint8_t> dest; + dest.resize(width*2*height*2*4); + + { + DVector<uint8_t>::Read r = data.read(); + DVector<uint8_t>::Write w = dest.write(); + + hq2x_resize((const uint32_t*)r.ptr(),width,height,(uint32_t*)w.ptr()); + + } + + width*=2; + height*=2; + data=dest; + + + if (current!=FORMAT_RGBA) + convert(current); + + if (mipmaps) { + generate_mipmaps(); + } + +} + +void Image::shrink_x2() { + + ERR_FAIL_COND(format==FORMAT_INDEXED || format==FORMAT_INDEXED_ALPHA); + ERR_FAIL_COND( data.size()==0 ); + + + + if (mipmaps) { + + //just use the lower mipmap as base and copy all + DVector<uint8_t> new_img; + + int ofs = get_mipmap_offset(1); + + int new_size = data.size()-ofs; + new_img.resize(new_size); + + + { + DVector<uint8_t>::Write w=new_img.write(); + DVector<uint8_t>::Read r=data.read(); + + copymem(w.ptr(),&r[ofs],new_size); + } + + mipmaps--; + width/=2; + height/=2; + data=new_img; + + } else { + + DVector<uint8_t> new_img; + + ERR_FAIL_COND( format>=FORMAT_INDEXED ); + int ps = get_format_pixel_size(format); + new_img.resize((width/2)*(height/2)*ps); + + { + DVector<uint8_t>::Write w=new_img.write(); + DVector<uint8_t>::Read r=data.read(); + + switch(format) { + + case FORMAT_GRAYSCALE: + case FORMAT_INTENSITY: _generate_po2_mipmap<1>(r.ptr(), w.ptr(), width,height); break; + case FORMAT_GRAYSCALE_ALPHA: _generate_po2_mipmap<2>(r.ptr(), w.ptr(), width,height); break; + case FORMAT_RGB: _generate_po2_mipmap<3>(r.ptr(), w.ptr(), width,height); break; + case FORMAT_RGBA: _generate_po2_mipmap<4>(r.ptr(), w.ptr(), width,height); break; + default: {} + } + } + + width/=2; + height/=2; + data=new_img; + + } +} + Error Image::generate_mipmaps(int p_mipmaps,bool p_keep_existing) { if (!_can_modify(format)) { diff --git a/core/image.h b/core/image.h index fe1822f661..0f0b345eb9 100644 --- a/core/image.h +++ b/core/image.h @@ -249,6 +249,8 @@ public: void resize_to_po2(bool p_square=false); void resize( int p_width, int p_height, Interpolation p_interpolation=INTERPOLATE_BILINEAR ); Image resized( int p_width, int p_height, int p_interpolation=INTERPOLATE_BILINEAR ); + void shrink_x2(); + void expand_x2_hq2x(); /** * Crop the image to a specific size, if larger, then the image is filled by black */ diff --git a/core/input_map.cpp b/core/input_map.cpp index 5a9b035771..08ee8138a3 100644 --- a/core/input_map.cpp +++ b/core/input_map.cpp @@ -28,6 +28,7 @@ /*************************************************************************/ #include "input_map.h" #include "globals.h" +#include "os/keyboard.h" InputMap *InputMap::singleton=NULL; @@ -36,6 +37,7 @@ void InputMap::_bind_methods() { ObjectTypeDB::bind_method(_MD("has_action","action"),&InputMap::has_action); ObjectTypeDB::bind_method(_MD("get_action_id","action"),&InputMap::get_action_id); ObjectTypeDB::bind_method(_MD("get_action_from_id","id"),&InputMap::get_action_from_id); + ObjectTypeDB::bind_method(_MD("get_actions"),&InputMap::_get_actions); ObjectTypeDB::bind_method(_MD("add_action","action"),&InputMap::add_action); ObjectTypeDB::bind_method(_MD("erase_action","action"),&InputMap::erase_action); @@ -75,6 +77,35 @@ StringName InputMap::get_action_from_id(int p_id) const { return input_id_map[p_id]; } +Array InputMap::_get_actions() { + + Array ret; + List<StringName> actions = get_actions(); + if(actions.empty()) + return ret; + + for(const List<StringName>::Element *E=actions.front();E;E=E->next()) { + + ret.push_back(E->get()); + } + + return ret; +} + +List<StringName> InputMap::get_actions() const { + + List<StringName> actions = List<StringName>(); + if(input_map.empty()){ + return actions; + } + + for (Map<StringName, Action>::Element *E=input_map.front();E;E=E->next()) { + actions.push_back(E->key()); + } + + return actions; +} + List<InputEvent>::Element *InputMap::_find_event(List<InputEvent> &p_list,const InputEvent& p_event) const { for (List<InputEvent>::Element *E=p_list.front();E;E=E->next()) { @@ -106,7 +137,7 @@ List<InputEvent>::Element *InputMap::_find_event(List<InputEvent> &p_list,const } break; case InputEvent::JOYSTICK_MOTION: { - same=(e.joy_motion.axis==p_event.joy_motion.axis); + same=(e.joy_motion.axis==p_event.joy_motion.axis && (e.joy_motion.axis_value < 0) == (p_event.joy_motion.axis_value < 0)); } break; } @@ -291,6 +322,67 @@ void InputMap::load_from_globals() { } +void InputMap::load_default() { + + InputEvent key; + key.type=InputEvent::KEY; + + add_action("ui_accept"); + key.key.scancode=KEY_RETURN; + action_add_event("ui_accept",key); + key.key.scancode=KEY_ENTER; + action_add_event("ui_accept",key); + key.key.scancode=KEY_SPACE; + action_add_event("ui_accept",key); + + add_action("ui_select"); + key.key.scancode=KEY_SPACE; + action_add_event("ui_select",key); + + add_action("ui_cancel"); + key.key.scancode=KEY_ESCAPE; + action_add_event("ui_cancel",key); + + add_action("ui_focus_next"); + key.key.scancode=KEY_TAB; + action_add_event("ui_focus_next",key); + + add_action("ui_focus_prev"); + key.key.scancode=KEY_TAB; + key.key.mod.shift=true; + action_add_event("ui_focus_prev",key); + key.key.mod.shift=false; + + add_action("ui_left"); + key.key.scancode=KEY_LEFT; + action_add_event("ui_left",key); + + add_action("ui_right"); + key.key.scancode=KEY_RIGHT; + action_add_event("ui_right",key); + + add_action("ui_up"); + key.key.scancode=KEY_UP; + action_add_event("ui_up",key); + + add_action("ui_down"); + key.key.scancode=KEY_DOWN; + action_add_event("ui_down",key); + + + add_action("ui_page_up"); + key.key.scancode=KEY_PAGEUP; + action_add_event("ui_page_up",key); + + add_action("ui_page_down"); + key.key.scancode=KEY_PAGEDOWN; + action_add_event("ui_page_down",key); + +// set("display/orientation", "landscape"); + + +} + InputMap::InputMap() { ERR_FAIL_COND(singleton); diff --git a/core/input_map.h b/core/input_map.h index 5cd1e41922..dc5a911963 100644 --- a/core/input_map.h +++ b/core/input_map.h @@ -47,6 +47,7 @@ class InputMap : public Object { List<InputEvent>::Element *_find_event(List<InputEvent> &p_list,const InputEvent& p_event) const; Array _get_action_list(const StringName& p_action); + Array _get_actions(); protected: @@ -59,6 +60,7 @@ public: bool has_action(const StringName& p_action) const; int get_action_id(const StringName& p_action) const; StringName get_action_from_id(int p_id) const; + List<StringName> get_actions() const; void add_action(const StringName& p_action); void erase_action(const StringName& p_action); @@ -72,6 +74,7 @@ public: void load_from_globals(); + void load_default(); InputMap(); }; diff --git a/core/io/LICENSE-InfoZip.txt b/core/io/LICENSE-InfoZip.txt new file mode 100644 index 0000000000..bcfe47e978 --- /dev/null +++ b/core/io/LICENSE-InfoZip.txt @@ -0,0 +1,60 @@ +This is version 2007-Mar-4 of the Info-ZIP license. +The definitive version of this document should be available at +ftp://ftp.info-zip.org/pub/infozip/license.html indefinitely and +a copy at http://www.info-zip.org/pub/infozip/license.html. + + +Copyright (c) 1990-2007 Info-ZIP. All rights reserved. + +For the purposes of this copyright and license, "Info-ZIP" is defined as +the following set of individuals: + + Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois, + Jean-loup Gailly, Hunter Goatley, Ed Gordon, Ian Gorman, Chris Herborth, + Dirk Haase, Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz, + David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko, + Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs, + Kai Uwe Rommel, Steve Salisbury, Dave Smith, Steven M. Schweda, + Christian Spieler, Cosmin Truta, Antoine Verheijen, Paul von Behren, + Rich Wales, Mike White. + +This software is provided "as is," without warranty of any kind, express +or implied. In no event shall Info-ZIP or its contributors be held liable +for any direct, indirect, incidental, special or consequential damages +arising out of the use of or inability to use this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the above disclaimer and the following restrictions: + + 1. Redistributions of source code (in whole or in part) must retain + the above copyright notice, definition, disclaimer, and this list + of conditions. + + 2. Redistributions in binary form (compiled executables and libraries) + must reproduce the above copyright notice, definition, disclaimer, + and this list of conditions in documentation and/or other materials + provided with the distribution. The sole exception to this condition + is redistribution of a standard UnZipSFX binary (including SFXWiz) as + part of a self-extracting archive; that is permitted without inclusion + of this license, as long as the normal SFX banner has not been removed + from the binary or disabled. + + 3. Altered versions--including, but not limited to, ports to new operating + systems, existing ports with new graphical interfaces, versions with + modified or added functionality, and dynamic, shared, or static library + versions not from Info-ZIP--must be plainly marked as such and must not + be misrepresented as being the original source or, if binaries, + compiled from the original source. Such altered versions also must not + be misrepresented as being Info-ZIP releases--including, but not + limited to, labeling of the altered versions with the names "Info-ZIP" + (or any variation thereof, including, but not limited to, different + capitalizations), "Pocket UnZip," "WiZ" or "MacZip" without the + explicit permission of Info-ZIP. Such altered versions are further + prohibited from misrepresentative use of the Zip-Bugs or Info-ZIP + e-mail addresses or the Info-ZIP URL(s), such as to imply Info-ZIP + will provide support for the altered versions. + + 4. Info-ZIP retains the right to use the names "Info-ZIP," "Zip," "UnZip," + "UnZipSFX," "WiZ," "Pocket UnZip," "Pocket Zip," and "MacZip" for its + own source and binary releases. diff --git a/core/io/LICENSE-MiniZip.txt b/core/io/LICENSE-MiniZip.txt new file mode 100644 index 0000000000..0e8950f86f --- /dev/null +++ b/core/io/LICENSE-MiniZip.txt @@ -0,0 +1,32 @@ +Credits + + Gilles Vollant - Original MiniZip author + Even Rouault - ZIP64 unzip Support + Daniel Borca - BZip Compression method support in unzip + Mathias Svensson - ZIP64 zip support + Mathias Svensson - BZip Compression method support in zip + + This version has been modified for Godot Engine + + +License +---------------------------------------------------------------------------- + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + +---------------------------------------------------------------------------- diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp index fd20ec9404..e0dc7ef9fa 100644 --- a/core/io/config_file.cpp +++ b/core/io/config_file.cpp @@ -207,7 +207,7 @@ Error ConfigFile::load(const String& p_path) { void ConfigFile::_bind_methods(){ ObjectTypeDB::bind_method(_MD("set_value","section","key","value"),&ConfigFile::set_value); - ObjectTypeDB::bind_method(_MD("get_value","section","key","default"),&ConfigFile::get_value,DEFVAL(Variant())); + ObjectTypeDB::bind_method(_MD("get_value:Variant","section","key","default"),&ConfigFile::get_value,DEFVAL(Variant())); ObjectTypeDB::bind_method(_MD("has_section","section"),&ConfigFile::has_section); ObjectTypeDB::bind_method(_MD("has_section_key","section","key"),&ConfigFile::has_section_key); diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp index 2cc52a9e2d..7db3499505 100644 --- a/core/io/file_access_memory.cpp +++ b/core/io/file_access_memory.cpp @@ -135,7 +135,7 @@ size_t FileAccessMemory::get_len() const { bool FileAccessMemory::eof_reached() const { - return pos >= length; + return pos > length; } uint8_t FileAccessMemory::get_8() const { diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index e0c01c9422..3520680118 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -72,7 +72,6 @@ Error HTTPClient::connect(const String &p_host, int p_port, bool p_ssl,bool p_ve return OK; } - void HTTPClient::set_connection(const Ref<StreamPeer>& p_connection){ close(); @@ -80,6 +79,65 @@ void HTTPClient::set_connection(const Ref<StreamPeer>& p_connection){ } +Ref<StreamPeer> HTTPClient::get_connection() const { + + return connection; +} + +Error HTTPClient::request_raw( Method p_method, const String& p_url, const Vector<String>& p_headers,const DVector<uint8_t>& p_body) { + + ERR_FAIL_INDEX_V(p_method,METHOD_MAX,ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V(status!=STATUS_CONNECTED,ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V(connection.is_null(),ERR_INVALID_DATA); + + + static const char* _methods[METHOD_MAX]={ + "GET", + "HEAD", + "POST", + "PUT", + "DELETE", + "OPTIONS", + "TRACE", + "CONNECT"}; + + String request=String(_methods[p_method])+" "+p_url+" HTTP/1.1\r\n"; + request+="Host: "+conn_host+":"+itos(conn_port)+"\r\n"; + bool add_clen=p_body.size()>0; + for(int i=0;i<p_headers.size();i++) { + request+=p_headers[i]+"\r\n"; + if (add_clen && p_headers[i].find("Content-Length:")==0) { + add_clen=false; + } + } + if (add_clen) { + request+="Content-Length: "+itos(p_body.size())+"\r\n"; + //should it add utf8 encoding? not sure + } + request+="\r\n"; + CharString cs=request.utf8(); + + DVector<uint8_t> data; + + //Maybe this goes faster somehow? + for(int i=0;i<cs.length();i++) { + data.append( cs[i] ); + } + data.append_array( p_body ); + + DVector<uint8_t>::Read r = data.read(); + Error err = connection->put_data(&r[0], data.size()); + + if (err) { + close(); + status=STATUS_CONNECTION_ERROR; + return err; + } + + status=STATUS_REQUESTING; + + return OK; +} Error HTTPClient::request( Method p_method, const String& p_url, const Vector<String>& p_headers,const String& p_body) { @@ -151,6 +209,7 @@ int HTTPClient::get_response_code() const { return response_num; } + Error HTTPClient::get_response_headers(List<String> *r_response) { if (!response_headers.size()) @@ -297,6 +356,7 @@ Error HTTPClient::poll(){ chunked=false; body_left=0; chunk_left=0; + response_str.clear(); response_headers.clear(); response_num = RESPONSE_OK; @@ -578,6 +638,8 @@ void HTTPClient::_bind_methods() { ObjectTypeDB::bind_method(_MD("connect:Error","host","port","use_ssl","verify_host"),&HTTPClient::connect,DEFVAL(false),DEFVAL(true)); ObjectTypeDB::bind_method(_MD("set_connection","connection:StreamPeer"),&HTTPClient::set_connection); + ObjectTypeDB::bind_method(_MD("get_connection:StreamPeer"),&HTTPClient::get_connection); + ObjectTypeDB::bind_method(_MD("request_raw","method","url","headers","body"),&HTTPClient::request_raw); ObjectTypeDB::bind_method(_MD("request","method","url","headers","body"),&HTTPClient::request,DEFVAL(String())); ObjectTypeDB::bind_method(_MD("send_body_text","body"),&HTTPClient::send_body_text); ObjectTypeDB::bind_method(_MD("send_body_data","body"),&HTTPClient::send_body_data); diff --git a/core/io/http_client.h b/core/io/http_client.h index e795646c70..ceb0273a7d 100644 --- a/core/io/http_client.h +++ b/core/io/http_client.h @@ -40,7 +40,7 @@ class HTTPClient : public Reference { OBJ_TYPE(HTTPClient,Reference); public: - enum RespondeCode { + enum ResponseCode { // 1xx informational RESPONSE_CONTINUE = 100, @@ -168,7 +168,9 @@ public: Error connect(const String &p_host,int p_port,bool p_ssl=false,bool p_verify_host=true); void set_connection(const Ref<StreamPeer>& p_connection); + Ref<StreamPeer> get_connection() const; + Error request_raw( Method p_method, const String& p_url, const Vector<String>& p_headers,const DVector<uint8_t>& p_body); Error request( Method p_method, const String& p_url, const Vector<String>& p_headers,const String& p_body=String()); Error send_body_text(const String& p_body); Error send_body_data(const ByteArray& p_body); diff --git a/core/io/ioapi.c b/core/io/ioapi.c index 8818199f0b..d6063a5fe6 100644 --- a/core/io/ioapi.c +++ b/core/io/ioapi.c @@ -6,7 +6,7 @@ Modifications for Zip64 support Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - For more info read MiniZip_info.txt + For more info read LICENSE-MiniZip.txt */ diff --git a/core/io/ioapi.h b/core/io/ioapi.h index 24bf612617..cb6cb7e766 100644 --- a/core/io/ioapi.h +++ b/core/io/ioapi.h @@ -5,7 +5,7 @@ Modifications for Zip64 support Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - For more info read MiniZip_info.txt + For more info read LICENSE-MiniZip.txt Changes diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp index 1733aecd46..60617e1237 100644 --- a/core/io/marshalls.cpp +++ b/core/io/marshalls.cpp @@ -438,8 +438,9 @@ Error decode_variant(Variant& r_variant,const uint8_t *p_buffer, int p_len,int * case InputEvent::JOYSTICK_MOTION: { ie.joy_motion.axis=decode_uint32(&buf[12]); + ie.joy_motion.axis_value=decode_float(&buf[16]); if (r_len) - (*r_len)+=4; + (*r_len)+=8; } break; } @@ -1154,8 +1155,9 @@ Error encode_variant(const Variant& p_variant, uint8_t *r_buffer, int &r_len) { int axis = ie.joy_motion.axis; encode_uint32(axis,&buf[llen]); + encode_float(ie.joy_motion.axis_value, &buf[llen+4]); } - llen+=4; + llen+=8; } break; } diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index abb1082256..1bb80e74eb 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -243,6 +243,7 @@ Ref<ResourceImportMetadata> ResourceLoader::load_import_metadata(const String &p break; } + return ret; } @@ -318,7 +319,11 @@ Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_ if (OS::get_singleton()->is_stdout_verbose()) print_line("load resource: "+local_path+" (cached)"); - return RES( ResourceCache::get(local_path ) ); + Ref<Resource> res_cached = ResourceCache::get(local_path); + Ref<ResourceInteractiveLoaderDefault> ril = Ref<ResourceInteractiveLoaderDefault>(memnew(ResourceInteractiveLoaderDefault)); + + ril->resource = res_cached; + return ril; } if (OS::get_singleton()->is_stdout_verbose()) diff --git a/core/io/translation_loader_po.cpp b/core/io/translation_loader_po.cpp index fe101a8676..4ddb276a27 100644 --- a/core/io/translation_loader_po.cpp +++ b/core/io/translation_loader_po.cpp @@ -30,13 +30,8 @@ #include "os/file_access.h" #include "translation.h" -RES TranslationLoaderPO::load(const String &p_path, const String& p_original_path, Error *r_error) { - if (r_error) - *r_error=ERR_CANT_OPEN; - - FileAccess *f=FileAccess::open(p_path,FileAccess::READ); - ERR_FAIL_COND_V(!f,RES()); +RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error, const String &p_path) { String l = f->get_line(); @@ -52,6 +47,8 @@ RES TranslationLoaderPO::load(const String &p_path, const String& p_original_pat String msg_id; String msg_str; String config; + int msg_line=0; + if (r_error) *r_error=ERR_FILE_CORRUPT; @@ -87,7 +84,7 @@ RES TranslationLoaderPO::load(const String &p_path, const String& p_original_pat if (status==STATUS_READING_ID) { memdelete(f); - ERR_EXPLAIN(p_path+":"+itos(line)+" nexpected 'msgid', was expecting 'msgstr' while parsing: "); + ERR_EXPLAIN(p_path+":"+itos(line)+" Unexpected 'msgid', was expecting 'msgstr' while parsing: "); ERR_FAIL_V(RES()); } @@ -100,6 +97,7 @@ RES TranslationLoaderPO::load(const String &p_path, const String& p_original_pat status=STATUS_READING_ID; msg_id=""; msg_str=""; + msg_line=line; } if (l.begins_with("msgstr")) { @@ -113,6 +111,7 @@ RES TranslationLoaderPO::load(const String &p_path, const String& p_original_pat l=l.substr(6,l.length()).strip_edges(); status=STATUS_READING_STRING; + msg_line=line; } if (l=="" || l.begins_with("#")) { @@ -183,6 +182,18 @@ RES TranslationLoaderPO::load(const String &p_path, const String& p_original_pat *r_error=OK; return translation; +} + +RES TranslationLoaderPO::load(const String &p_path, const String& p_original_path, Error *r_error) { + + if (r_error) + *r_error=ERR_CANT_OPEN; + + FileAccess *f=FileAccess::open(p_path,FileAccess::READ); + ERR_FAIL_COND_V(!f,RES()); + + + return load_translation(f,r_error); } diff --git a/core/io/translation_loader_po.h b/core/io/translation_loader_po.h index a569674d80..b0c4e42682 100644 --- a/core/io/translation_loader_po.h +++ b/core/io/translation_loader_po.h @@ -30,10 +30,12 @@ #define TRANSLATION_LOADER_PO_H #include "io/resource_loader.h" - +#include "translation.h" +#include "os/file_access.h" class TranslationLoaderPO : public ResourceFormatLoader { public: + static RES load_translation(FileAccess *f, Error *r_error,const String& p_path=String()); virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String& p_type) const; diff --git a/core/io/unzip.c b/core/io/unzip.c index b438021ad7..78672677f9 100644 --- a/core/io/unzip.c +++ b/core/io/unzip.c @@ -10,7 +10,7 @@ Modifications for Zip64 support on both zip and unzip Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - For more info read MiniZip_info.txt + For more info read LICENSE-MiniZip.txt ------------------------------------------------------------------------------------ diff --git a/core/io/unzip.h b/core/io/unzip.h index cb3d239eac..f67c3b2fa8 100644 --- a/core/io/unzip.h +++ b/core/io/unzip.h @@ -10,7 +10,7 @@ Modifications for Zip64 support on both zip and unzip Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - For more info read MiniZip_info.txt + For more info read LICENSE-MiniZip.txt --------------------------------------------------------------------------------- diff --git a/core/io/zip.c b/core/io/zip.c index c4ab93ab81..44c79195d9 100644 --- a/core/io/zip.c +++ b/core/io/zip.c @@ -7,7 +7,7 @@ Modifications for Zip64 support Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - For more info read MiniZip_info.txt + For more info read LICENSE-MiniZip.txt Changes Oct-2009 - Mathias Svensson - Remove old C style function prototypes diff --git a/core/io/zip.h b/core/io/zip.h index 85f93568c9..37478b34c0 100644 --- a/core/io/zip.h +++ b/core/io/zip.h @@ -6,7 +6,7 @@ Modifications for Zip64 support Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - For more info read MiniZip_info.txt + For more info read LICENSE-MiniZip.txt --------------------------------------------------------------------------- diff --git a/core/make_binders.py b/core/make_binders.py index ebd48777b6..93371dc0a3 100644 --- a/core/make_binders.py +++ b/core/make_binders.py @@ -6,7 +6,7 @@ template_typed=""" template<class T $ifret ,class R$ $ifargs ,$ $arg, class P@$> class MethodBind$argc$$ifret R$$ifconst C$ : public MethodBind { public: - + $ifret R$ $ifnoret void$ (T::*method)($arg, P@$) $ifconst const$; #ifdef DEBUG_METHODS_ENABLED virtual Variant::Type _gen_argument_type(int p_arg) const { return _get_argument_type(p_arg); } @@ -16,13 +16,13 @@ public: $ return Variant::NIL; } -#endif +#endif virtual String get_instance_type() const { return T::get_type_static(); } virtual Variant call(Object* p_object,const Variant** p_args,int p_arg_count, Variant::CallError& r_error) { - + T *instance=p_object->cast_to<T>(); r_error.error=Variant::CallError::CALL_OK; #ifdef DEBUG_METHODS_ENABLED @@ -47,7 +47,7 @@ public: $ifret return Variant(ret);$ $ifnoret return Variant();$ } - + MethodBind$argc$$ifret R$$ifconst C$ () { #ifdef DEBUG_METHODS_ENABLED @@ -55,14 +55,14 @@ public: _generate_argument_types($argc$); #else set_argument_count($argc$); -#endif +#endif }; }; template<class T $ifret ,class R$ $ifargs ,$ $arg, class P@$> MethodBind* create_method_bind($ifret R$ $ifnoret void$ (T::*p_method)($arg, P@$) $ifconst const$ ) { - MethodBind$argc$$ifret R$$ifconst C$<T $ifret ,R$ $ifargs ,$ $arg, P@$> * a = memnew( (MethodBind$argc$$ifret R$$ifconst C$<T $ifret ,R$ $ifargs ,$ $arg, P@$>) ); + MethodBind$argc$$ifret R$$ifconst C$<T $ifret ,R$ $ifargs ,$ $arg, P@$> * a = memnew( (MethodBind$argc$$ifret R$$ifconst C$<T $ifret ,R$ $ifargs ,$ $arg, P@$>) ); a->method=p_method; return a; } @@ -88,7 +88,7 @@ public: $ return Variant::NIL; } -#endif +#endif virtual String get_instance_type() const { return type_name; } @@ -105,15 +105,15 @@ public: r_error.error=Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; r_error.argument=get_argument_count(); return Variant(); - } - + } + if (p_arg_count<(get_argument_count()-get_default_argument_count())) { r_error.error=Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.argument=get_argument_count()-get_default_argument_count(); return Variant(); } - + $arg CHECK_ARG(@); $ #endif @@ -128,7 +128,7 @@ public: _generate_argument_types($argc$); #else set_argument_count($argc$); -#endif +#endif }; }; @@ -151,12 +151,12 @@ MethodBind* create_method_bind($ifret R$ $ifnoret void$ (T::*p_method)($arg, P@$ def make_version(template,nargs,argmax,const,ret): - + intext=template from_pos=0 outtext="" - - while(True): + + while(True): to_pos=intext.find("$",from_pos) if (to_pos==-1): outtext+=intext[from_pos:] @@ -169,13 +169,13 @@ def make_version(template,nargs,argmax,const,ret): macro=intext[to_pos+1:end] cmd="" data="" - + if (macro.find(" ")!=-1): cmd=macro[0:macro.find(" ")] data=macro[macro.find(" ")+1:] else: cmd=macro - + if (cmd=="argc"): outtext+=str(nargs) if (cmd=="ifret" and ret): @@ -206,11 +206,11 @@ def make_version(template,nargs,argmax,const,ret): elif (cmd=="noarg"): for i in range(nargs+1,argmax+1): outtext+=data.replace("@",str(i)) - + from_pos=end+1 - + return outtext - + def run(target, source, env): @@ -244,9 +244,9 @@ def run(target, source, env): f.write(text_ext) f.close() - - - - - + + + + + diff --git a/core/math/math_defs.h b/core/math/math_defs.h index eb85039ca3..e6a56c5e45 100644 --- a/core/math/math_defs.h +++ b/core/math/math_defs.h @@ -34,6 +34,7 @@ #define CMP_NORMALIZE_TOLERANCE 0.000001 #define CMP_POINT_IN_PLANE_EPSILON 0.00001 +#define USEC_TO_SEC(m_usec) ((m_usec)/1000000.0) /** * "Real" is a type that will be translated to either floats or fixed depending * on the compilation setting diff --git a/core/math/math_funcs.cpp b/core/math/math_funcs.cpp index 07f114725d..0fbd031214 100644 --- a/core/math/math_funcs.cpp +++ b/core/math/math_funcs.cpp @@ -135,18 +135,20 @@ double Math::rad2deg(double p_y) { double Math::round(double p_val) { - if (p_val>0) { + if (p_val>=0) { return ::floor(p_val+0.5); } else { p_val=-p_val; return -::floor(p_val+0.5); } } + double Math::asin(double p_x) { return ::asin(p_x); } + double Math::acos(double p_x) { return ::acos(p_x); diff --git a/core/object.cpp b/core/object.cpp index 7bdec06c1b..cbe24a49f3 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -463,6 +463,11 @@ void Object::get_property_list(List<PropertyInfo> *p_list,bool p_reversed) const } } + +void Object::_validate_property(PropertyInfo& property) const { + +} + void Object::get_method_list(List<MethodInfo> *p_list) const { ObjectTypeDB::get_method_list(get_type_name(),p_list); @@ -1244,6 +1249,7 @@ void Object::emit_signal(const StringName& p_name,VARIANT_ARG_DECLARE) { argc++; } + emit_signal(p_name,argptr,argc); } @@ -1377,6 +1383,31 @@ void Object::get_signal_connection_list(const StringName& p_signal,List<Connecti } +bool Object::has_persistent_signal_connections() const { + + const StringName *S=NULL; + + while((S=signal_map.next(S))) { + + const Signal *s=&signal_map[*S]; + + for(int i=0;i<s->slot_map.size();i++) { + + if (s->slot_map.getv(i).conn.flags&CONNECT_PERSIST) + return true; + } + } + + return false; +} + +void Object::get_signals_connected_to_this(List<Connection> *p_connections) const { + + for (const List<Connection>::Element *E=connections.front();E;E=E->next()) { + p_connections->push_back(E->get()); + } +} + Error Object::connect(const StringName& p_signal, Object *p_to_object, const StringName& p_to_method,const Vector<Variant>& p_binds,uint32_t p_flags) { @@ -1390,7 +1421,7 @@ Error Object::connect(const StringName& p_signal, Object *p_to_object, const Str signal_is_valid=true; if (!signal_is_valid) { - ERR_EXPLAIN("Attempt to connect nonexistent signal '"+p_signal+"' to method '"+p_to_method+"'"); + ERR_EXPLAIN("In Object of type '"+String(get_type())+"': Attempt to connect nonexistent signal '"+p_signal+"' to method '"+p_to_object->get_type()+"."+p_to_method+"'"); ERR_FAIL_COND_V(!signal_is_valid,ERR_INVALID_PARAMETER); } signal_map[p_signal]=Signal(); @@ -1750,6 +1781,7 @@ bool Object::is_queued_for_deletion() const { void Object::set_edited(bool p_edited) { _edited=p_edited; + _edited_version++; } bool Object::is_edited() const { @@ -1757,6 +1789,11 @@ bool Object::is_edited() const { return _edited; } + +uint32_t Object::get_edited_version() const { + + return _edited_version; +} #endif Object::Object() { @@ -1772,6 +1809,7 @@ Object::Object() { #ifdef TOOLS_ENABLED _edited=false; + _edited_version=0; #endif #ifdef DEBUG_ENABLED diff --git a/core/object.h b/core/object.h index dcebf9b2a2..ce545a58e8 100644 --- a/core/object.h +++ b/core/object.h @@ -67,6 +67,7 @@ enum PropertyHint { PROPERTY_HINT_COLOR_NO_ALPHA, ///< used for ignoring alpha component when editing a color PROPERTY_HINT_IMAGE_COMPRESS_LOSSY, PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS, + PROPERTY_HINT_OBJECT_ID, PROPERTY_HINT_MAX, }; @@ -84,6 +85,7 @@ enum PropertyUsageFlags { PROPERTY_USAGE_STORE_IF_NONZERO=512, //only store if nonzero PROPERTY_USAGE_STORE_IF_NONONE=1024, //only store if false PROPERTY_USAGE_NO_INSTANCE_STATE=2048, + PROPERTY_USAGE_RESTART_IF_CHANGED=4096, PROPERTY_USAGE_DEFAULT=PROPERTY_USAGE_STORAGE|PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_NETWORK, PROPERTY_USAGE_DEFAULT_INTL=PROPERTY_USAGE_STORAGE|PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_NETWORK|PROPERTY_USAGE_INTERNATIONALIZED, @@ -274,12 +276,12 @@ virtual void _get_property_listv(List<PropertyInfo> *p_list,bool p_reversed) con }\ p_list->push_back( PropertyInfo(Variant::NIL,get_type_static(),PROPERTY_HINT_NONE,String(),PROPERTY_USAGE_CATEGORY));\ if (!_is_gpl_reversed())\ - ObjectTypeDB::get_property_list(#m_type,p_list,true);\ + ObjectTypeDB::get_property_list(#m_type,p_list,true,this);\ if (m_type::_get_get_property_list() != m_inherits::_get_get_property_list()) {\ _get_property_list(p_list);\ }\ if (_is_gpl_reversed())\ - ObjectTypeDB::get_property_list(#m_type,p_list,true);\ + ObjectTypeDB::get_property_list(#m_type,p_list,true,this);\ if (p_reversed) {\ m_inherits::_get_property_listv(p_list,p_reversed);\ }\ @@ -387,6 +389,7 @@ friend void postinitialize_handler(Object*); bool _can_translate; #ifdef TOOLS_ENABLED bool _edited; + uint32_t _edited_version; #endif ScriptInstance *script_instance; RefPtr script; @@ -462,6 +465,9 @@ protected: void _clear_internal_resource_paths(const Variant &p_var); +friend class ObjectTypeDB; + virtual void _validate_property(PropertyInfo& property) const; + public: //should be protected, but bug in clang++ static void initialize_type(); _FORCE_INLINE_ static void register_custom_data_to_otdb() {}; @@ -585,6 +591,7 @@ public: #ifdef TOOLS_ENABLED void set_edited(bool p_edited); bool is_edited() const; + uint32_t get_edited_version() const; //this function is used to check when something changed beyond a point, it's used mainly for generating previews #endif void set_script_instance(ScriptInstance *p_instance); @@ -597,6 +604,8 @@ public: void get_signal_list(List<MethodInfo> *p_signals ) const; void get_signal_connection_list(const StringName& p_signal,List<Connection> *p_connections) const; void get_all_signal_connections(List<Connection> *p_connections) const; + bool has_persistent_signal_connections() const; + void get_signals_connected_to_this(List<Connection> *p_connections) const; Error connect(const StringName& p_signal, Object *p_to_object, const StringName& p_to_method,const Vector<Variant>& p_binds=Vector<Variant>(),uint32_t p_flags=0); void disconnect(const StringName& p_signal, Object *p_to_object, const StringName& p_to_method); diff --git a/core/object_type_db.cpp b/core/object_type_db.cpp index 14b595d61b..5f97df39a6 100644 --- a/core/object_type_db.cpp +++ b/core/object_type_db.cpp @@ -619,14 +619,22 @@ void ObjectTypeDB::add_property(StringName p_type,const PropertyInfo& p_pinfo, c } -void ObjectTypeDB::get_property_list(StringName p_type,List<PropertyInfo> *p_list,bool p_no_inheritance) { +void ObjectTypeDB::get_property_list(StringName p_type, List<PropertyInfo> *p_list, bool p_no_inheritance,const Object *p_validator) { TypeInfo *type=types.getptr(p_type); TypeInfo *check=type; while(check) { for(List<PropertyInfo>::Element *E=type->property_list.front();E;E=E->next()) { - p_list->push_back(E->get()); + + + if (p_validator) { + PropertyInfo pi = E->get(); + p_validator->_validate_property(pi); + p_list->push_back(pi); + } else { + p_list->push_back(E->get()); + } } if (p_no_inheritance) diff --git a/core/object_type_db.h b/core/object_type_db.h index a4896fff81..8313091acd 100644 --- a/core/object_type_db.h +++ b/core/object_type_db.h @@ -456,7 +456,7 @@ public: static void get_signal_list(StringName p_type,List<MethodInfo> *p_signals,bool p_no_inheritance=false); static void add_property(StringName p_type,const PropertyInfo& p_pinfo, const StringName& p_setter, const StringName& p_getter, int p_index=-1); - static void get_property_list(StringName p_type,List<PropertyInfo> *p_list,bool p_no_inheritance=false); + static void get_property_list(StringName p_type, List<PropertyInfo> *p_list, bool p_no_inheritance=false, const Object *p_validator=NULL); static bool set_property(Object* p_object, const StringName& p_property, const Variant& p_value, bool *r_valid=NULL); static bool get_property(Object* p_object,const StringName& p_property, Variant& r_value); static Variant::Type get_property_type(const StringName& p_type, const StringName& p_property,bool *r_is_valid=NULL); diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp index 0846ef3eb0..a3ee9395de 100644 --- a/core/os/file_access.cpp +++ b/core/os/file_access.cpp @@ -284,7 +284,7 @@ Vector<String> FileAccess::get_csv_line(String delim) const { String l; int qc=0; do { - l+=get_line(); + l+=get_line()+"\n"; qc=0; for(int i=0;i<l.length();i++) { @@ -295,6 +295,8 @@ Vector<String> FileAccess::get_csv_line(String delim) const { } while (qc%2); + l=l.substr(0, l.length()-1); + Vector<String> strings; bool in_quote=false; diff --git a/core/os/input.cpp b/core/os/input.cpp index 6e1e618d9a..a766ef87fc 100644 --- a/core/os/input.cpp +++ b/core/os/input.cpp @@ -60,6 +60,7 @@ void Input::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_joy_name","device"),&Input::get_joy_name); ObjectTypeDB::bind_method(_MD("get_joy_guid","device"),&Input::get_joy_guid); ObjectTypeDB::bind_method(_MD("get_accelerometer"),&Input::get_accelerometer); + ObjectTypeDB::bind_method(_MD("get_magnetometer"),&Input::get_magnetometer); //ObjectTypeDB::bind_method(_MD("get_mouse_pos"),&Input::get_mouse_pos); - this is not the function you want ObjectTypeDB::bind_method(_MD("get_mouse_speed"),&Input::get_mouse_speed); ObjectTypeDB::bind_method(_MD("get_mouse_button_mask"),&Input::get_mouse_button_mask); diff --git a/core/os/input.h b/core/os/input.h index 535776f39c..46edb30aa1 100644 --- a/core/os/input.h +++ b/core/os/input.h @@ -75,6 +75,7 @@ public: virtual void warp_mouse_pos(const Vector2& p_to)=0; virtual Vector3 get_accelerometer()=0; + virtual Vector3 get_magnetometer()=0; virtual void action_press(const StringName& p_action)=0; virtual void action_release(const StringName& p_action)=0; diff --git a/core/os/main_loop.cpp b/core/os/main_loop.cpp index 310bbaa3b8..e5feebfbfc 100644 --- a/core/os/main_loop.cpp +++ b/core/os/main_loop.cpp @@ -43,6 +43,7 @@ void MainLoop::_bind_methods() { BIND_VMETHOD( MethodInfo("_initialize") ); BIND_VMETHOD( MethodInfo("_iteration",PropertyInfo(Variant::REAL,"delta")) ); BIND_VMETHOD( MethodInfo("_idle",PropertyInfo(Variant::REAL,"delta")) ); + BIND_VMETHOD( MethodInfo("_drop_files",PropertyInfo(Variant::STRING_ARRAY,"files"),PropertyInfo(Variant::INT,"screen")) ); BIND_VMETHOD( MethodInfo("_finalize") ); BIND_CONSTANT(NOTIFICATION_WM_MOUSE_ENTER); @@ -108,6 +109,15 @@ bool MainLoop::idle(float p_time) { return false; } + +void MainLoop::drop_files(const Vector<String>& p_files,int p_from_screen) { + + + if (get_script_instance()) + get_script_instance()->call("_drop_files",p_files,p_from_screen); + +} + void MainLoop::finish() { if (get_script_instance()) { diff --git a/core/os/main_loop.h b/core/os/main_loop.h index a34014983e..57185d9d3d 100644 --- a/core/os/main_loop.h +++ b/core/os/main_loop.h @@ -64,6 +64,8 @@ public: virtual bool idle(float p_time); virtual void finish(); + virtual void drop_files(const Vector<String>& p_files,int p_from_screen=0); + void set_init_script(const Ref<Script>& p_init_script); MainLoop(); diff --git a/core/os/memory.h b/core/os/memory.h index 8257e66851..5f4c6f929c 100644 --- a/core/os/memory.h +++ b/core/os/memory.h @@ -211,7 +211,7 @@ void * operator new(size_t p_size,void *p_pointer,size_t check, const char *p_de #ifdef DEBUG_MEMORY_ENABLED -#define memalloc(m_size) Memory::alloc_static(m_size, __FILE__":"__STR(__LINE__)", memalloc.") +#define memalloc(m_size) Memory::alloc_static(m_size, __FILE__ ":" __STR(__LINE__) ", memalloc.") #define memrealloc(m_mem,m_size) Memory::realloc_static(m_mem,m_size) #define memfree(m_size) Memory::free_static(m_size) @@ -224,8 +224,7 @@ void * operator new(size_t p_size,void *p_pointer,size_t check, const char *p_de #endif #ifdef DEBUG_MEMORY_ENABLED - -#define dynalloc(m_size) Memory::alloc_dynamic(m_size, __FILE__":"__STR(__LINE__)", type: DYNAMIC") +#define dynalloc(m_size) Memory::alloc_dynamic(m_size, __FILE__ ":" __STR(__LINE__) ", type: DYNAMIC") #define dynrealloc(m_mem,m_size) m_mem.resize(m_size) #else @@ -248,7 +247,7 @@ _ALWAYS_INLINE_ T *_post_initialize(T *p_obj) { #ifdef DEBUG_MEMORY_ENABLED -#define memnew(m_class) _post_initialize(new(__FILE__":"__STR(__LINE__)", memnew type: "__STR(m_class)) m_class) +#define memnew(m_class) _post_initialize(new(__FILE__ ":" __STR(__LINE__) ", memnew type: " __STR(m_class)) m_class) #else @@ -291,7 +290,7 @@ void memdelete_allocator(T *p_class) { #define memdelete_notnull(m_v) { if (m_v) memdelete(m_v); } #ifdef DEBUG_MEMORY_ENABLED -#define memnew_arr( m_class, m_count ) memnew_arr_template<m_class>(m_count,__FILE__":"__STR(__LINE__)", memnew_arr type: "_STR(m_class)) +#define memnew_arr( m_class, m_count ) memnew_arr_template<m_class>(m_count,__FILE__ ":" __STR(__LINE__) ", memnew_arr type: " _STR(m_class)) #else diff --git a/core/os/os.cpp b/core/os/os.cpp index 1aee6d9aa2..e501bc2eb5 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -306,6 +306,15 @@ String OS::get_system_dir(SystemDir p_dir) const { return "."; } +String OS::get_safe_application_name() const { + String an = Globals::get_singleton()->get("application/name"); + Vector<String> invalid_char = String("\\ / : * ? \" < > |").split(" "); + for (int i=0;i<invalid_char.size();i++) { + an = an.replace(invalid_char[i],"-"); + } + return an; +} + String OS::get_data_dir() const { return "."; @@ -530,6 +539,14 @@ String OS::get_joy_guid(int p_device) const { void OS::set_context(int p_context) { } +void OS::set_use_vsync(bool p_enable) { + +} + +bool OS::is_vsnc_enabled() const{ + + return true; +} OS::OS() { last_error=NULL; @@ -548,6 +565,7 @@ OS::OS() { _render_thread_mode=RENDER_THREAD_SAFE; _time_scale=1.0; _pixel_snap=false; + _allow_hidpi=true; Math::seed(1234567); } diff --git a/core/os/os.h b/core/os/os.h index 160c0495bb..c291d09250 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -60,6 +60,7 @@ class OS { int _target_fps; float _time_scale; bool _pixel_snap; + bool _allow_hidpi; char *last_error; @@ -160,6 +161,7 @@ public: virtual void set_current_screen(int p_screen) { } virtual Point2 get_screen_position(int p_screen=0) const { return Point2(); } virtual Size2 get_screen_size(int p_screen=0) const { return get_window_size(); } + virtual int get_screen_dpi(int p_screen=0) const { return 72; } virtual Point2 get_window_position() const { return Vector2(); } virtual void set_window_position(const Point2& p_position) {} virtual Size2 get_window_size() const=0; @@ -324,6 +326,7 @@ public: virtual String get_locale() const; + String get_safe_application_name() const; virtual String get_data_dir() const; virtual String get_resource_dir() const; @@ -417,6 +420,10 @@ public: virtual void set_context(int p_context); + virtual void set_use_vsync(bool p_enable); + virtual bool is_vsnc_enabled() const; + + bool is_hidpi_allowed() const { return _allow_hidpi; } OS(); virtual ~OS(); diff --git a/core/print_string.cpp b/core/print_string.cpp index e364388b7b..6e57822e94 100644 --- a/core/print_string.cpp +++ b/core/print_string.cpp @@ -66,7 +66,7 @@ void remove_print_handler(PrintHandlerList *p_handler) { l=l->next; } - OS::get_singleton()->print("print handler list is %p\n",print_handler_list); + //OS::get_singleton()->print("print handler list is %p\n",print_handler_list); ERR_FAIL_COND(l==NULL); _global_unlock(); diff --git a/core/profile_clock.cpp b/core/profile_clock.cpp new file mode 100644 index 0000000000..0806275463 --- /dev/null +++ b/core/profile_clock.cpp @@ -0,0 +1,3 @@ +#include "profile_clock.h" + + diff --git a/core/profile_clock.h b/core/profile_clock.h new file mode 100644 index 0000000000..e254580249 --- /dev/null +++ b/core/profile_clock.h @@ -0,0 +1,7 @@ +#ifndef PROFILE_CLOCK_H +#define PROFILE_CLOCK_H + + + + +#endif // PROFILE_CLOCK_H diff --git a/core/resource.cpp b/core/resource.cpp index 672e64b1bb..97dee3e1d7 100644 --- a/core/resource.cpp +++ b/core/resource.cpp @@ -133,6 +133,7 @@ void ResourceImportMetadata::_bind_methods() { ObjectTypeDB::bind_method(_MD("add_source","path","md5"),&ResourceImportMetadata::add_source, ""); ObjectTypeDB::bind_method(_MD("get_source_path","idx"),&ResourceImportMetadata::get_source_path); ObjectTypeDB::bind_method(_MD("get_source_md5","idx"),&ResourceImportMetadata::get_source_md5); + ObjectTypeDB::bind_method(_MD("set_source_md5","idx", "md5"),&ResourceImportMetadata::set_source_md5); ObjectTypeDB::bind_method(_MD("remove_source","idx"),&ResourceImportMetadata::remove_source); ObjectTypeDB::bind_method(_MD("get_source_count"),&ResourceImportMetadata::get_source_count); ObjectTypeDB::bind_method(_MD("set_option","key","value"),&ResourceImportMetadata::set_option); @@ -330,6 +331,31 @@ Ref<ResourceImportMetadata> Resource::get_import_metadata() const { } +#ifdef TOOLS_ENABLED + +uint32_t Resource::hash_edited_version() const { + + uint32_t hash = hash_djb2_one_32(get_edited_version()); + + List<PropertyInfo> plist; + get_property_list(&plist); + + for (List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) { + + if (E->get().type==Variant::OBJECT && E->get().hint==PROPERTY_HINT_RESOURCE_TYPE) { + RES res = get(E->get().name); + if (res.is_valid()) { + hash = hash_djb2_one_32(res->hash_edited_version(),hash); + } + } + } + + return hash; + +} + +#endif + Resource::Resource() { @@ -341,6 +367,8 @@ Resource::Resource() { } + + Resource::~Resource() { if (path_cache!="") diff --git a/core/resource.h b/core/resource.h index 8bcdd6b4b7..958414f62b 100644 --- a/core/resource.h +++ b/core/resource.h @@ -142,8 +142,12 @@ public: Ref<ResourceImportMetadata> get_import_metadata() const; + + #ifdef TOOLS_ENABLED + uint32_t hash_edited_version() const; + virtual void set_last_modified_time(uint64_t p_time) { last_modified_time=p_time; } uint64_t get_last_modified_time() const { return last_modified_time; } diff --git a/core/script_debugger_local.cpp b/core/script_debugger_local.cpp index 3e442f7f59..dfff54378a 100644 --- a/core/script_debugger_local.cpp +++ b/core/script_debugger_local.cpp @@ -179,6 +179,125 @@ void ScriptDebuggerLocal::debug(ScriptLanguage *p_script,bool p_can_continue) { } } +struct _ScriptDebuggerLocalProfileInfoSort { + + bool operator()(const ScriptLanguage::ProfilingInfo &A,const ScriptLanguage::ProfilingInfo &B) const { + return A.total_time > B.total_time; + } +}; + +void ScriptDebuggerLocal::profiling_set_frame_times(float p_frame_time,float p_idle_time,float p_fixed_time,float p_fixed_frame_time) { + + + frame_time=p_frame_time; + idle_time=p_idle_time; + fixed_time=p_fixed_time; + fixed_frame_time=p_fixed_frame_time; + + +} + +void ScriptDebuggerLocal::idle_poll() { + + if (!profiling) + return; + + uint64_t diff = OS::get_singleton()->get_ticks_usec() - idle_accum; + + if (diff<1000000) //show every one second + return; + + idle_accum = OS::get_singleton()->get_ticks_usec(); + + int ofs=0; + for(int i=0;i<ScriptServer::get_language_count();i++) { + ofs+=ScriptServer::get_language(i)->profiling_get_frame_data(&pinfo[ofs],pinfo.size()-ofs); + } + + SortArray<ScriptLanguage::ProfilingInfo,_ScriptDebuggerLocalProfileInfoSort> sort; + sort.sort(pinfo.ptr(),ofs); + + //falta el frame time + + uint64_t script_time_us=0; + + for(int i=0;i<ofs;i++) { + + script_time_us+=pinfo[i].self_time; + } + + + float script_time=USEC_TO_SEC(script_time_us); + + float total_time=frame_time; + + //print script total + + print_line("FRAME: total: "+rtos(frame_time)+" script: "+rtos(script_time)+"/"+itos(script_time*100/total_time)+" %"); + + for(int i=0;i<ofs;i++) { + + print_line(itos(i)+":"+pinfo[i].signature); + float tt=USEC_TO_SEC(pinfo[i].total_time); + float st=USEC_TO_SEC(pinfo[i].self_time); + print_line("\ttotal: "+rtos(tt)+"/"+itos(tt*100/total_time)+" % \tself: "+rtos(st)+"/"+itos(st*100/total_time)+" % tcalls: "+itos(pinfo[i].call_count)); + } + + + +} + +void ScriptDebuggerLocal::profiling_start() { + + for(int i=0;i<ScriptServer::get_language_count();i++) { + ScriptServer::get_language(i)->profiling_start(); + } + + + print_line("BEGIN PROFILING"); + profiling=true; + pinfo.resize(32768); + frame_time=0; + fixed_time=0; + idle_time=0; + fixed_frame_time=0; + +} + + +void ScriptDebuggerLocal::profiling_end() { + + int ofs=0; + + for(int i=0;i<ScriptServer::get_language_count();i++) { + ofs+=ScriptServer::get_language(i)->profiling_get_accumulated_data(&pinfo[ofs],pinfo.size()-ofs); + } + + SortArray<ScriptLanguage::ProfilingInfo,_ScriptDebuggerLocalProfileInfoSort> sort; + sort.sort(pinfo.ptr(),ofs); + + uint64_t total_us=0; + for(int i=0;i<ofs;i++) { + total_us+=pinfo[i].self_time; + } + + float total_time=total_us/1000000.0; + + for(int i=0;i<ofs;i++) { + + print_line(itos(i)+":"+pinfo[i].signature); + float tt=USEC_TO_SEC(pinfo[i].total_time);; + float st=USEC_TO_SEC(pinfo[i].self_time); + print_line("\ttotal_ms: "+rtos(tt)+"\tself_ms: "+rtos(st)+"total%: "+itos(tt*100/total_time)+"\tself%: "+itos(st*100/total_time)+"\tcalls: "+itos(pinfo[i].call_count)); + } + + for(int i=0;i<ScriptServer::get_language_count();i++) { + ScriptServer::get_language(i)->profiling_stop(); + } + + profiling=false; +} + void ScriptDebuggerLocal::send_message(const String& p_message, const Array &p_args) { print_line("MESSAGE: '"+p_message+"' - "+String(Variant(p_args))); @@ -186,4 +305,6 @@ void ScriptDebuggerLocal::send_message(const String& p_message, const Array &p_a ScriptDebuggerLocal::ScriptDebuggerLocal() { + profiling=false; + idle_accum=OS::get_singleton()->get_ticks_usec(); } diff --git a/core/script_debugger_local.h b/core/script_debugger_local.h index 4abacfc519..ffe8dce445 100644 --- a/core/script_debugger_local.h +++ b/core/script_debugger_local.h @@ -32,10 +32,29 @@ #include "script_language.h" class ScriptDebuggerLocal : public ScriptDebugger { + + bool profiling; + float frame_time,idle_time,fixed_time,fixed_frame_time; + uint64_t idle_accum; + + Vector<ScriptLanguage::ProfilingInfo> pinfo; + + public: void debug(ScriptLanguage *p_script,bool p_can_continue); virtual void send_message(const String& p_message, const Array& p_args); + + virtual bool is_profiling() const { return profiling; } + virtual void add_profiling_frame_data(const StringName& p_name,const Array& p_data) {} + + virtual void idle_poll(); + + virtual void profiling_start(); + virtual void profiling_end(); + virtual void profiling_set_frame_times(float p_frame_time,float p_idle_time,float p_fixed_time,float p_fixed_frame_time); + + ScriptDebuggerLocal(); }; diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp index b56ff4c0e1..99d1e22c07 100644 --- a/core/script_debugger_remote.cpp +++ b/core/script_debugger_remote.cpp @@ -125,6 +125,10 @@ static ObjectID safe_get_instance_id(const Variant& p_v) { void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) { + //this function is called when there is a debugger break (bug on script) + //or when execution is paused from editor + + if (!tcp_client->is_connected()) { ERR_EXPLAIN("Script Debugger failed to connect, but being used anyway."); ERR_FAIL(); @@ -135,6 +139,8 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) { packet_peer_stream->put_var(p_can_continue); packet_peer_stream->put_var(p_script->debug_get_error()); + skip_profile_frame=true; // to avoid super long frame time for the frame + Input::MouseMode mouse_mode=Input::get_singleton()->get_mouse_mode(); if (mouse_mode!=Input::MOUSE_MODE_VISIBLE) Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); @@ -277,6 +283,16 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) { } else if (command=="request_video_mem") { _send_video_memory(); + } else if (command=="inspect_object") { + + ObjectID id = cmd[1]; + _send_object_id(id); + } else if (command=="set_object_property") { + + _set_object_property(cmd[1],cmd[2],cmd[3]); + + } else if (command=="reload_scripts") { + reload_all_scripts=true; } else if (command=="breakpoint") { bool set = cmd[3]; @@ -372,7 +388,7 @@ void ScriptDebuggerRemote::line_poll() { //the purpose of this is just processing events every now and then when the script might get too busy //otherwise bugs like infinite loops cant be catched - if (poll_every%512==0) + if (poll_every%2048==0) _poll_events(); poll_every++; @@ -533,8 +549,94 @@ bool ScriptDebuggerRemote::_parse_live_edit(const Array& cmd) { return true; } + +void ScriptDebuggerRemote::_send_object_id(ObjectID p_id) { + + Object* obj = ObjectDB::get_instance(p_id); + if (!obj) + return; + + List<PropertyInfo> pinfo; + obj->get_property_list(&pinfo,true); + + int props_to_send=0; + for (List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) { + + if (E->get().usage&(PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_CATEGORY)) { + props_to_send++; + } + } + + packet_peer_stream->put_var("message:inspect_object"); + packet_peer_stream->put_var(props_to_send*5+4); + packet_peer_stream->put_var(p_id); + packet_peer_stream->put_var(obj->get_type()); + if (obj->is_type("Resource") || obj->is_type("Node")) + packet_peer_stream->put_var(obj->call("get_path")); + else + packet_peer_stream->put_var(""); + + packet_peer_stream->put_var(props_to_send); + + for (List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) { + + if (E->get().usage&(PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_CATEGORY)) { + + if (E->get().usage&PROPERTY_USAGE_CATEGORY) { + packet_peer_stream->put_var("*"+E->get().name); + } else { + packet_peer_stream->put_var(E->get().name); + } + + Variant var = obj->get(E->get().name); + + if (E->get().type==Variant::OBJECT || var.get_type()==Variant::OBJECT) { + + ObjectID id2; + Object *obj=var; + if (obj) { + id2=obj->get_instance_ID(); + } else { + id2=0; + } + + packet_peer_stream->put_var(Variant::INT); //hint string + packet_peer_stream->put_var(PROPERTY_HINT_OBJECT_ID); //hint + packet_peer_stream->put_var(E->get().hint_string); //hint string + packet_peer_stream->put_var(id2); //value + } else { + packet_peer_stream->put_var(E->get().type); + packet_peer_stream->put_var(E->get().hint); + packet_peer_stream->put_var(E->get().hint_string); + //only send information that can be sent.. + if (var.get_type()==Variant::IMAGE) { + var=Image(); + } + if (var.get_type()>=Variant::DICTIONARY) { + var=Array(); //send none for now, may be to big + } + packet_peer_stream->put_var(var); + } + + } + } + +} + +void ScriptDebuggerRemote::_set_object_property(ObjectID p_id, const String& p_property, const Variant& p_value) { + + Object* obj = ObjectDB::get_instance(p_id); + if (!obj) + return; + + obj->set(p_property,p_value); +} + void ScriptDebuggerRemote::_poll_events() { + //this si called from ::idle_poll, happens only when running the game, + //does not get called while on debug break + while(packet_peer_stream->get_available_packet_count()>0) { _get_output(); @@ -566,6 +668,40 @@ void ScriptDebuggerRemote::_poll_events() { } else if (command=="request_video_mem") { _send_video_memory(); + } else if (command=="inspect_object") { + + ObjectID id = cmd[1]; + _send_object_id(id); + } else if (command=="set_object_property") { + + _set_object_property(cmd[1],cmd[2],cmd[3]); + + } else if (command=="start_profiling") { + + for(int i=0;i<ScriptServer::get_language_count();i++) { + ScriptServer::get_language(i)->profiling_start(); + } + + max_frame_functions=cmd[1]; + profiler_function_signature_map.clear(); + profiling=true; + frame_time=0; + idle_time=0; + fixed_time=0; + fixed_frame_time=0; + + print_line("PROFILING ALRIGHT!"); + + } else if (command=="stop_profiling") { + + for(int i=0;i<ScriptServer::get_language_count();i++) { + ScriptServer::get_language(i)->profiling_stop(); + } + profiling=false; + _send_profiling_data(false); + print_line("PROFILING END!"); + } else if (command=="reload_scripts") { + reload_all_scripts=true; } else if (command=="breakpoint") { bool set = cmd[3]; @@ -582,8 +718,113 @@ void ScriptDebuggerRemote::_poll_events() { } +void ScriptDebuggerRemote::_send_profiling_data(bool p_for_frame) { + + + + + int ofs=0; + + for(int i=0;i<ScriptServer::get_language_count();i++) { + if (p_for_frame) + ofs+=ScriptServer::get_language(i)->profiling_get_frame_data(&profile_info[ofs],profile_info.size()-ofs); + else + ofs+=ScriptServer::get_language(i)->profiling_get_accumulated_data(&profile_info[ofs],profile_info.size()-ofs); + } + + for(int i=0;i<ofs;i++) { + profile_info_ptrs[i]=&profile_info[i]; + } + + SortArray<ScriptLanguage::ProfilingInfo*,ProfileInfoSort> sa; + sa.sort(profile_info_ptrs.ptr(),ofs); + + int to_send=MIN(ofs,max_frame_functions); + + //check signatures first + uint64_t total_script_time=0; + + for(int i=0;i<to_send;i++) { + + if (!profiler_function_signature_map.has(profile_info_ptrs[i]->signature)) { + + int idx = profiler_function_signature_map.size(); + packet_peer_stream->put_var("profile_sig"); + packet_peer_stream->put_var(2); + packet_peer_stream->put_var(profile_info_ptrs[i]->signature); + packet_peer_stream->put_var(idx); + + profiler_function_signature_map[profile_info_ptrs[i]->signature]=idx; + + + } + + total_script_time+=profile_info_ptrs[i]->self_time; + } + + //send frames then + + if (p_for_frame) { + packet_peer_stream->put_var("profile_frame"); + packet_peer_stream->put_var(8+profile_frame_data.size()*2+to_send*4); + } else { + packet_peer_stream->put_var("profile_total"); + packet_peer_stream->put_var(8+to_send*4); + } + + + packet_peer_stream->put_var(OS::get_singleton()->get_frames_drawn()); //total frame time + packet_peer_stream->put_var(frame_time); //total frame time + packet_peer_stream->put_var(idle_time); //idle frame time + packet_peer_stream->put_var(fixed_time); //fixed frame time + packet_peer_stream->put_var(fixed_frame_time); //fixed frame time + + packet_peer_stream->put_var(USEC_TO_SEC(total_script_time)); //total script execution time + + if (p_for_frame) { + + packet_peer_stream->put_var(profile_frame_data.size()); //how many profile framedatas to send + packet_peer_stream->put_var(to_send); //how many script functions to send + for (int i=0;i<profile_frame_data.size();i++) { + + + packet_peer_stream->put_var(profile_frame_data[i].name); + packet_peer_stream->put_var(profile_frame_data[i].data); + } + } else { + packet_peer_stream->put_var(0); //how many script functions to send + packet_peer_stream->put_var(to_send); //how many script functions to send + } + + + + for(int i=0;i<to_send;i++) { + + int sig_id=-1; + + if (profiler_function_signature_map.has(profile_info_ptrs[i]->signature)) { + sig_id=profiler_function_signature_map[profile_info_ptrs[i]->signature]; + } + + + + packet_peer_stream->put_var(sig_id); + packet_peer_stream->put_var(profile_info_ptrs[i]->call_count); + packet_peer_stream->put_var(profile_info_ptrs[i]->total_time/1000000.0); + packet_peer_stream->put_var(profile_info_ptrs[i]->self_time/1000000.0); + } + + if (p_for_frame) { + profile_frame_data.clear(); + } + +} + void ScriptDebuggerRemote::idle_poll() { + // this function is called every frame, except when there is a debugger break (::debug() in this class) + // execution stops and remains in the ::debug function + _get_output(); @@ -615,6 +856,24 @@ void ScriptDebuggerRemote::idle_poll() { } } + if (profiling) { + + if (skip_profile_frame) { + skip_profile_frame=false; + } else { + //send profiling info normally + _send_profiling_data(true); + } + } + + if (reload_all_scripts) { + + for(int i=0;i<ScriptServer::get_language_count();i++) { + ScriptServer::get_language(i)->reload_all_scripts(); + } + reload_all_scripts=false; + } + _poll_events(); } @@ -687,6 +946,50 @@ void ScriptDebuggerRemote::set_live_edit_funcs(LiveEditFuncs *p_funcs) { live_edit_funcs=p_funcs; } +bool ScriptDebuggerRemote::is_profiling() const { + + return profiling; +} +void ScriptDebuggerRemote::add_profiling_frame_data(const StringName& p_name,const Array& p_data){ + + int idx=-1; + for(int i=0;i<profile_frame_data.size();i++) { + if (profile_frame_data[i].name==p_name) { + idx=i; + break; + } + } + + FrameData fd; + fd.name=p_name; + fd.data=p_data; + + if (idx==-1) { + profile_frame_data.push_back(fd); + } else { + profile_frame_data[idx]=fd; + } +} + +void ScriptDebuggerRemote::profiling_start() { + //ignores this, uses it via connnection +} + +void ScriptDebuggerRemote::profiling_end() { + //ignores this, uses it via connnection +} + +void ScriptDebuggerRemote::profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_fixed_time, float p_fixed_frame_time) { + + frame_time=p_frame_time; + idle_time=p_idle_time; + fixed_time=p_fixed_time; + fixed_frame_time=p_fixed_frame_time; + + +} + + ScriptDebuggerRemote::ResourceUsageFunc ScriptDebuggerRemote::resource_usage_func=NULL; ScriptDebuggerRemote::ScriptDebuggerRemote() { @@ -710,11 +1013,18 @@ ScriptDebuggerRemote::ScriptDebuggerRemote() { char_count=0; msec_count=0; last_msec=0; + skip_profile_frame=false; eh.errfunc=_err_handler; eh.userdata=this; add_error_handler(&eh); + profile_info.resize(CLAMP(int(Globals::get_singleton()->get("debug/profiler_max_functions")),128,65535)); + profile_info_ptrs.resize(profile_info.size()); + profiling=false; + max_frame_functions=16; + reload_all_scripts=false; + } ScriptDebuggerRemote::~ScriptDebuggerRemote() { @@ -723,4 +1033,5 @@ ScriptDebuggerRemote::~ScriptDebuggerRemote() { remove_error_handler(&eh); memdelete(mutex); + } diff --git a/core/script_debugger_remote.h b/core/script_debugger_remote.h index f18e212236..c6a00e189f 100644 --- a/core/script_debugger_remote.h +++ b/core/script_debugger_remote.h @@ -44,6 +44,24 @@ class ScriptDebuggerRemote : public ScriptDebugger { }; + struct ProfileInfoSort { + + bool operator()(ScriptLanguage::ProfilingInfo*A,ScriptLanguage::ProfilingInfo*B) const { + return A->total_time < B->total_time; + } + }; + + Vector<ScriptLanguage::ProfilingInfo> profile_info; + Vector<ScriptLanguage::ProfilingInfo*> profile_info_ptrs; + + Map<StringName,int> profiler_function_signature_map; + float frame_time,idle_time,fixed_time,fixed_frame_time; + + bool profiling; + int max_frame_functions; + bool skip_profile_frame; + bool reload_all_scripts; + Ref<StreamPeerTCP> tcp_client; Ref<PacketPeerStream> packet_peer_stream; @@ -88,17 +106,32 @@ class ScriptDebuggerRemote : public ScriptDebugger { uint32_t poll_every; + bool _parse_live_edit(const Array &p_command); RequestSceneTreeMessageFunc request_scene_tree; void *request_scene_tree_ud; + void _set_object_property(ObjectID p_id, const String& p_property, const Variant& p_value); + + void _send_object_id(ObjectID p_id); void _send_video_memory(); LiveEditFuncs *live_edit_funcs; ErrorHandlerList eh; static void _err_handler(void*,const char*,const char*,int p_line,const char *, const char *,ErrorHandlerType p_type); + void _send_profiling_data(bool p_for_frame); + + + struct FrameData { + + StringName name; + Array data; + }; + + Vector<FrameData> profile_frame_data; + public: @@ -129,6 +162,14 @@ public: virtual void set_request_scene_tree_message_func(RequestSceneTreeMessageFunc p_func, void *p_udata); virtual void set_live_edit_funcs(LiveEditFuncs *p_funcs); + virtual bool is_profiling() const; + virtual void add_profiling_frame_data(const StringName& p_name,const Array& p_data); + + virtual void profiling_start(); + virtual void profiling_end(); + virtual void profiling_set_frame_times(float p_frame_time,float p_idle_time,float p_fixed_time,float p_fixed_frame_time); + + ScriptDebuggerRemote(); ~ScriptDebuggerRemote(); }; diff --git a/core/script_language.cpp b/core/script_language.cpp index 1503418269..b3116a0297 100644 --- a/core/script_language.cpp +++ b/core/script_language.cpp @@ -51,7 +51,7 @@ void Script::_bind_methods() { ObjectTypeDB::bind_method(_MD("has_source_code"),&Script::has_source_code); ObjectTypeDB::bind_method(_MD("get_source_code"),&Script::get_source_code); ObjectTypeDB::bind_method(_MD("set_source_code","source"),&Script::set_source_code); - ObjectTypeDB::bind_method(_MD("reload"),&Script::reload); + ObjectTypeDB::bind_method(_MD("reload","keep_state"),&Script::reload,DEFVAL(false)); } diff --git a/core/script_language.h b/core/script_language.h index 1be1aabdab..d8b4c61b6c 100644 --- a/core/script_language.h +++ b/core/script_language.h @@ -87,7 +87,7 @@ public: virtual bool has_source_code() const=0; virtual String get_source_code() const=0; virtual void set_source_code(const String& p_code)=0; - virtual Error reload()=0; + virtual Error reload(bool p_keep_state=false)=0; virtual bool is_tool() const=0; @@ -127,6 +127,8 @@ public: virtual Ref<Script> get_script() const=0; + virtual bool is_placeholder() const { return false; } + virtual ScriptLanguage *get_language()=0; virtual ~ScriptInstance(); }; @@ -189,12 +191,28 @@ public: virtual Vector<StackInfo> debug_get_current_stack_info() { return Vector<StackInfo>(); } + virtual void reload_all_scripts()=0; /* LOADER FUNCTIONS */ virtual void get_recognized_extensions(List<String> *p_extensions) const=0; virtual void get_public_functions(List<MethodInfo> *p_functions) const=0; virtual void get_public_constants(List<Pair<String,Variant> > *p_constants) const=0; + struct ProfilingInfo { + StringName signature; + uint64_t call_count; + uint64_t total_time; + uint64_t self_time; + + }; + + virtual void profiling_start()=0; + virtual void profiling_stop()=0; + + virtual int profiling_get_accumulated_data(ProfilingInfo *p_info_arr,int p_info_max)=0; + virtual int profiling_get_frame_data(ProfilingInfo *p_info_arr,int p_info_max)=0; + + virtual void frame(); virtual ~ScriptLanguage() {}; @@ -233,6 +251,8 @@ public: void update(const List<PropertyInfo> &p_properties,const Map<StringName,Variant>& p_values); //likely changed in editor + virtual bool is_placeholder() const { return true; } + PlaceHolderScriptInstance(ScriptLanguage *p_language, Ref<Script> p_script,Object *p_owner); ~PlaceHolderScriptInstance(); @@ -309,6 +329,13 @@ public: virtual void set_request_scene_tree_message_func(RequestSceneTreeMessageFunc p_func, void *p_udata) {} virtual void set_live_edit_funcs(LiveEditFuncs *p_funcs) {} + virtual bool is_profiling() const=0; + virtual void add_profiling_frame_data(const StringName& p_name,const Array& p_data)=0; + virtual void profiling_start()=0; + virtual void profiling_end()=0; + virtual void profiling_set_frame_times(float p_frame_time,float p_idle_time,float p_fixed_time,float p_fixed_frame_time)=0; + + ScriptDebugger(); virtual ~ScriptDebugger() {singleton=NULL;} diff --git a/core/translation.cpp b/core/translation.cpp index e4dad8d8de..ee0ef2ea09 100644 --- a/core/translation.cpp +++ b/core/translation.cpp @@ -665,6 +665,24 @@ void TranslationServer::setup() { } +void TranslationServer::set_tool_translation(const Ref<Translation>& p_translation) { + tool_translation=p_translation; +} + +StringName TranslationServer::tool_translate(const StringName& p_message) const { + + if (tool_translation.is_valid()) { + StringName r = tool_translation->get_message(p_message); + + if (r) { + return r; + } + } + + return p_message; +} + + void TranslationServer::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_locale","locale"),&TranslationServer::set_locale); diff --git a/core/translation.h b/core/translation.h index 5be6b8913a..cdb22bfeca 100644 --- a/core/translation.h +++ b/core/translation.h @@ -75,6 +75,7 @@ class TranslationServer : public Object { Set< Ref<Translation> > translations; + Ref<Translation> tool_translation; bool enabled; @@ -102,6 +103,9 @@ public: static Vector<String> get_all_locales(); static Vector<String> get_all_locale_names(); + void set_tool_translation(const Ref<Translation>& p_translation); + StringName tool_translate(const StringName& p_message) const; + void setup(); void clear(); diff --git a/core/typedefs.h b/core/typedefs.h index 5047644692..6f9bb58958 100644 --- a/core/typedefs.h +++ b/core/typedefs.h @@ -41,7 +41,11 @@ #define _MKSTR(m_x) _STR(m_x) #endif // have to include version.h for this to work, include it in the .cpp not the .h +#ifdef VERSION_PATCH +#define VERSION_MKSTRING _MKSTR(VERSION_MAJOR)"." _MKSTR(VERSION_MINOR)"." _MKSTR(VERSION_PATCH)"." _MKSTR(VERSION_STATUS)"." _MKSTR(VERSION_REVISION) +#else #define VERSION_MKSTRING _MKSTR(VERSION_MAJOR)"." _MKSTR(VERSION_MINOR)"." _MKSTR(VERSION_STATUS)"." _MKSTR(VERSION_REVISION) +#endif // VERSION_PATCH #define VERSION_FULL_NAME _MKSTR(VERSION_NAME)" v" VERSION_MKSTRING diff --git a/core/ustring.cpp b/core/ustring.cpp index a9d0012ebe..a039ba11cd 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -2867,25 +2867,29 @@ CharType String::ord_at(int p_idx) const { return operator[](p_idx); } -String String::strip_edges() const { +String String::strip_edges(bool left, bool right) const { int len=length(); int beg=0,end=len; - for (int i=0;i<length();i++) { + if(left) { + for (int i=0;i<len;i++) { - if (operator[](i)<=32) - beg++; - else - break; + if (operator[](i)<=32) + beg++; + else + break; + } } - for (int i=(int)(length()-1);i>=0;i--) { + if(right) { + for (int i=(int)(len-1);i>=0;i--) { - if (operator[](i)<=32) - end--; - else - break; + if (operator[](i)<=32) + end--; + else + break; + } } if (beg==0 && end==len) @@ -3629,13 +3633,14 @@ String String::percent_decode() const { CharString pe; - for(int i=0;i<length();i++) { + CharString cs = utf8(); + for(int i=0;i<cs.length();i++) { - uint8_t c=operator[](i); + uint8_t c = cs[i]; if (c=='%' && i<length()-2) { - uint8_t a = LOWERCASE(operator[](i+1)); - uint8_t b = LOWERCASE(operator[](i+2)); + uint8_t a = LOWERCASE(cs[i+1]); + uint8_t b = LOWERCASE(cs[i+2]); c=0; if (a>='0' && a<='9') @@ -3955,3 +3960,34 @@ String String::sprintf(const Array& values, bool* error) const { *error = false; return formatted; } + +#include "translation.h" + +#ifdef TOOLS_ENABLED +String TTR(const String& p_text) { + + if (TranslationServer::get_singleton()) { + return TranslationServer::get_singleton()->tool_translate(p_text); + } + + return p_text; +} + +#endif + +String RTR(const String& p_text) { + + + + if (TranslationServer::get_singleton()) { + String rtr = TranslationServer::get_singleton()->tool_translate(p_text); + if (rtr==String() || rtr==p_text) { + return TranslationServer::get_singleton()->translate(p_text); + } else { + return rtr; + } + } + + return p_text; +} + diff --git a/core/ustring.h b/core/ustring.h index 6310d0a854..e03f74f506 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -169,7 +169,7 @@ public: String left(int p_pos) const; String right(int p_pos) const; - String strip_edges() const; + String strip_edges(bool left = true, bool right = true) const; String strip_escapes() const; String extension() const; String basename() const; @@ -256,5 +256,18 @@ struct NoCaseComparator { /* end of namespace */ +//tool translate +#ifdef TOOLS_ENABLED + +String TTR(const String&); + +#else + +#define TTR(m_val) (String()) + +#endif + +//tool or regular translate +String RTR(const String&); #endif diff --git a/core/variant.cpp b/core/variant.cpp index 527a0d238f..38f5e69cc0 100644 --- a/core/variant.cpp +++ b/core/variant.cpp @@ -1556,6 +1556,18 @@ Variant::operator String() const { return str; } break; + case VECTOR2_ARRAY: { + + DVector<Vector2> vec = operator DVector<Vector2>(); + String str; + for(int i=0;i<vec.size();i++) { + + if (i>0) + str+=", "; + str=str+Variant( vec[i] ); + } + return str; + } break; case VECTOR3_ARRAY: { DVector<Vector3> vec = operator DVector<Vector3>(); @@ -3036,3 +3048,47 @@ String Variant::get_call_error_text(Object* p_base, const StringName& p_method,c } return "'"+class_name+"::"+String(p_method)+"': "+err_text; } + + +String vformat(const String& p_text, const Variant& p1,const Variant& p2,const Variant& p3,const Variant& p4,const Variant& p5) { + + Array args; + if (p1.get_type()!=Variant::NIL) { + + args.push_back(p1); + + if (p2.get_type()!=Variant::NIL) { + + args.push_back(p2); + + if (p3.get_type()!=Variant::NIL) { + + args.push_back(p3); + + if (p4.get_type()!=Variant::NIL) { + + args.push_back(p4); + + if (p5.get_type()!=Variant::NIL) { + + args.push_back(p5); + + } + + } + + + } + + } + + } + + bool error=false; + String fmt = p_text.sprintf(args,&error); + + ERR_FAIL_COND_V(error,String()); + + return fmt; + +} diff --git a/core/variant.h b/core/variant.h index ed33de6660..b95223ecfb 100644 --- a/core/variant.h +++ b/core/variant.h @@ -469,4 +469,6 @@ const Variant::ObjData& Variant::_get_obj() const { return *reinterpret_cast<const ObjData*>(&_data._mem[0]); } + +String vformat(const String& p_text, const Variant& p1=Variant(),const Variant& p2=Variant(),const Variant& p3=Variant(),const Variant& p4=Variant(),const Variant& p5=Variant()); #endif diff --git a/core/variant_call.cpp b/core/variant_call.cpp index 78814c83e2..eb3ab65f40 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -246,6 +246,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var VCALL_LOCALMEM1R(String,match); VCALL_LOCALMEM1R(String,matchn); VCALL_LOCALMEM1R(String,begins_with); + VCALL_LOCALMEM1R(String,ends_with); VCALL_LOCALMEM2R(String,replace); VCALL_LOCALMEM2R(String,replacen); VCALL_LOCALMEM2R(String,insert); @@ -256,12 +257,12 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var VCALL_LOCALMEM0R(String,to_lower); VCALL_LOCALMEM1R(String,left); VCALL_LOCALMEM1R(String,right); - VCALL_LOCALMEM0R(String,strip_edges); + VCALL_LOCALMEM2R(String,strip_edges); VCALL_LOCALMEM0R(String,extension); VCALL_LOCALMEM0R(String,basename); VCALL_LOCALMEM1R(String,plus_file); VCALL_LOCALMEM1R(String,ord_at); - //VCALL_LOCALMEM2R(String,erase); + VCALL_LOCALMEM2(String,erase); VCALL_LOCALMEM0R(String,hash); VCALL_LOCALMEM0R(String,md5_text); VCALL_LOCALMEM0R(String,md5_buffer); @@ -338,6 +339,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var VCALL_LOCALMEM1R(Vector2,reflect); VCALL_LOCALMEM0R(Vector2,angle); // VCALL_LOCALMEM1R(Vector2,cross); + VCALL_LOCALMEM0R(Vector2,abs); VCALL_LOCALMEM0R(Rect2,get_area); VCALL_LOCALMEM1R(Rect2,intersects); @@ -440,9 +442,11 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var VCALL_LOCALMEM0R(Dictionary,empty); VCALL_LOCALMEM0(Dictionary,clear); VCALL_LOCALMEM1R(Dictionary,has); + VCALL_LOCALMEM1R(Dictionary,has_all); VCALL_LOCALMEM1(Dictionary,erase); VCALL_LOCALMEM0R(Dictionary,hash); VCALL_LOCALMEM0R(Dictionary,keys); + VCALL_LOCALMEM0R(Dictionary,values); VCALL_LOCALMEM1R(Dictionary,parse_json); VCALL_LOCALMEM0R(Dictionary,to_json); @@ -461,6 +465,8 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var VCALL_LOCALMEM2(Array,insert); VCALL_LOCALMEM1(Array,remove); VCALL_LOCALMEM1R(Array,find); + VCALL_LOCALMEM1R(Array,find_last); + VCALL_LOCALMEM1R(Array,count); VCALL_LOCALMEM1(Array,erase); VCALL_LOCALMEM0(Array,sort); VCALL_LOCALMEM2(Array,sort_custom); @@ -593,6 +599,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var VCALL_PTR0R(Image, get_data); VCALL_PTR3(Image, blit_rect); VCALL_PTR1R(Image, converted); + VCALL_PTR0(Image, fix_alpha_edges); VCALL_PTR0R( AABB, get_area ); VCALL_PTR0R( AABB, has_no_area ); @@ -1260,6 +1267,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl ADDFUNC1(STRING,BOOL,String,match,STRING,"expr",varray()); ADDFUNC1(STRING,BOOL,String,matchn,STRING,"expr",varray()); ADDFUNC1(STRING,BOOL,String,begins_with,STRING,"text",varray()); + ADDFUNC1(STRING,BOOL,String,ends_with,STRING,"text",varray()); ADDFUNC2(STRING,STRING,String,replace,STRING,"what",STRING,"forwhat",varray()); ADDFUNC2(STRING,STRING,String,replacen,STRING,"what",STRING,"forwhat",varray()); @@ -1273,12 +1281,12 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl ADDFUNC1(STRING,STRING,String,left,INT,"pos",varray()); ADDFUNC1(STRING,STRING,String,right,INT,"pos",varray()); - ADDFUNC0(STRING,STRING,String,strip_edges,varray()); + ADDFUNC2(STRING,STRING,String,strip_edges,BOOL,"left",BOOL,"right",varray(true,true)); ADDFUNC0(STRING,STRING,String,extension,varray()); ADDFUNC0(STRING,STRING,String,basename,varray()); ADDFUNC1(STRING,STRING,String,plus_file,STRING,"file",varray()); ADDFUNC1(STRING,STRING,String,ord_at,INT,"at",varray()); -// ADDFUNC2(STRING,String,erase,INT,INT,varray()); + ADDFUNC2(STRING,NIL,String,erase,INT,"pos",INT,"chars", varray()); ADDFUNC0(STRING,INT,String,hash,varray()); ADDFUNC0(STRING,STRING,String,md5_text,varray()); ADDFUNC0(STRING,RAW_ARRAY,String,md5_buffer,varray()); @@ -1329,6 +1337,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl ADDFUNC1(VECTOR2,VECTOR2,Vector2,slide,VECTOR2,"vec",varray()); ADDFUNC1(VECTOR2,VECTOR2,Vector2,reflect,VECTOR2,"vec",varray()); //ADDFUNC1(VECTOR2,REAL,Vector2,cross,VECTOR2,"with",varray()); + ADDFUNC0(VECTOR2,VECTOR2,Vector2,abs,varray()); ADDFUNC0(RECT2,REAL,Rect2,get_area,varray()); ADDFUNC1(RECT2,BOOL,Rect2,intersects,RECT2,"b",varray()); @@ -1408,6 +1417,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl ADDFUNC0(IMAGE, RAW_ARRAY, Image, get_data, varray()); ADDFUNC3(IMAGE, NIL, Image, blit_rect, IMAGE, "src", RECT2, "src_rect", VECTOR2, "dest", varray(0)); ADDFUNC1(IMAGE, IMAGE, Image, converted, INT, "format", varray(0)); + ADDFUNC0(IMAGE, NIL, Image, fix_alpha_edges, varray()); ADDFUNC0(_RID,INT,RID,get_id,varray()); @@ -1423,9 +1433,11 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl ADDFUNC0(DICTIONARY,BOOL,Dictionary,empty,varray()); ADDFUNC0(DICTIONARY,NIL,Dictionary,clear,varray()); ADDFUNC1(DICTIONARY,BOOL,Dictionary,has,NIL,"value",varray()); + ADDFUNC1(DICTIONARY,BOOL,Dictionary,has_all,ARRAY,"values",varray()); ADDFUNC1(DICTIONARY,NIL,Dictionary,erase,NIL,"value",varray()); ADDFUNC0(DICTIONARY,INT,Dictionary,hash,varray()); ADDFUNC0(DICTIONARY,ARRAY,Dictionary,keys,varray()); + ADDFUNC0(DICTIONARY,ARRAY,Dictionary,values,varray()); ADDFUNC1(DICTIONARY,INT,Dictionary,parse_json,STRING,"json",varray()); ADDFUNC0(DICTIONARY,STRING,Dictionary,to_json,varray()); @@ -1442,6 +1454,8 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl ADDFUNC1(ARRAY,NIL,Array,remove,INT,"pos",varray()); ADDFUNC1(ARRAY,NIL,Array,erase,NIL,"value",varray()); ADDFUNC1(ARRAY,INT,Array,find,NIL,"value",varray()); + ADDFUNC1(ARRAY,INT,Array,find_last,NIL,"value",varray()); + ADDFUNC1(ARRAY,INT,Array,count,NIL,"value",varray()); ADDFUNC0(ARRAY,NIL,Array,pop_back,varray()); ADDFUNC0(ARRAY,NIL,Array,pop_front,varray()); ADDFUNC0(ARRAY,NIL,Array,sort,varray()); diff --git a/core/variant_op.cpp b/core/variant_op.cpp index f03ab43fce..6065094da7 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -1354,7 +1354,7 @@ void Variant::set(const Variant& p_index, const Variant& p_value, bool *r_valid) return; } else if (*str=="r8" ) { valid=true; - v->g=float(p_value)/255.0; + v->r=float(p_value)/255.0; return; } else if (*str=="g8" ) { valid=true; @@ -2213,16 +2213,16 @@ Variant Variant::get(const Variant& p_index, bool *r_valid) const { return v->get_v(); } else if (*str=="r8") { valid=true; - return v->r*255.0; + return (int)Math::round(v->r*255.0); } else if (*str=="g8" ) { valid=true; - return v->g*255.0; + return (int)Math::round(v->g*255.0); } else if (*str=="b8" ) { valid=true; - return v->b*255.0; + return (int)Math::round(v->b*255.0); } else if (*str=="a8" ) { valid=true; - return v->a*255.0; + return (int)Math::round(v->a*255.0); } } else if (p_index.get_type()==Variant::INT) { @@ -3513,7 +3513,7 @@ void Variant::interpolate(const Variant& a, const Variant& b, float c,Variant &r case INT:{ int va=a._data._int; int vb=b._data._int; - r_dst=int((1.0-c) * va + vb * c + 0.5); + r_dst=int((1.0-c) * va + vb * c); } return; case REAL:{ real_t va=a._data._real; diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp index 8bd1fddfad..e2786b8099 100644 --- a/core/variant_parser.cpp +++ b/core/variant_parser.cpp @@ -2011,7 +2011,44 @@ Error VariantWriter::write(const Variant& p_variant, StoreStringFunc p_store_str } break; case Variant::INPUT_EVENT: { - p_store_string_func(p_store_string_ud,"InputEvent()"); //will be added later + String str="InputEvent("; + + InputEvent ev=p_variant; + switch(ev.type) { + case InputEvent::KEY: { + + str+="KEY,"+itos(ev.key.scancode); + String mod; + if (ev.key.mod.alt) + mod+="A"; + if (ev.key.mod.shift) + mod+="S"; + if (ev.key.mod.control) + mod+="C"; + if (ev.key.mod.meta) + mod+="M"; + + if (mod!=String()) + str+=","+mod; + } break; + case InputEvent::MOUSE_BUTTON: { + + str+="MBUTTON,"+itos(ev.mouse_button.button_index); + } break; + case InputEvent::JOYSTICK_BUTTON: { + str+="JBUTTON,"+itos(ev.joy_button.button_index); + + } break; + case InputEvent::JOYSTICK_MOTION: { + str+="JAXIS,"+itos(ev.joy_motion.axis)+","+itos(ev.joy_motion.axis_value); + } break; + default: {} + } + + str+=")"; + + p_store_string_func(p_store_string_ud,str); //will be added later + } break; case Variant::DICTIONARY: { diff --git a/core/vector.h b/core/vector.h index 16a09c1ddd..87248ccf68 100644 --- a/core/vector.h +++ b/core/vector.h @@ -70,7 +70,8 @@ class Vector { } _FORCE_INLINE_ size_t _get_alloc_size(size_t p_elements) const { - return nearest_power_of_2_templated(p_elements*sizeof(T)+sizeof(SafeRefCount)+sizeof(int)); + //return nearest_power_of_2_templated(p_elements*sizeof(T)+sizeof(SafeRefCount)+sizeof(int)); + return nearest_power_of_2(p_elements*sizeof(T)+sizeof(SafeRefCount)+sizeof(int)); } _FORCE_INLINE_ bool _get_alloc_size_checked(size_t p_elements, size_t *out) const { @@ -79,7 +80,7 @@ class Vector { size_t p; if (_mul_overflow(p_elements, sizeof(T), &o)) return false; if (_add_overflow(o, sizeof(SafeRefCount)+sizeof(int), &p)) return false; - *out = nearest_power_of_2_templated(p); + *out = nearest_power_of_2(p); return true; #else // Speed is more important than correctness here, do the operations unchecked |