Making Godot Easier to Use..
-=-=-=-=-=-=-=-=-=-=-=-=-=-= -Auto indenter in code editor, this makes it much easier to paste external code. -Zoom in 2D viewport now uses the mouse pointer as reference. -Obscure hack to see where code/line of GDScript in C++ backtrace. -Fixed a bug where keys would get stuck on X11 if pressed simultaneously -Added Api on IP singleton to request local IPs. -Premultiplied alpha support when importing texture, editing PNGs and as a blend mode.
This commit is contained in:
parent
f9ff086235
commit
1cad087969
|
@ -98,6 +98,13 @@ void _ResourceSaver::_bind_methods() {
|
|||
|
||||
ObjectTypeDB::bind_method(_MD("save","path","resource:Resource"),&_ResourceSaver::save, DEFVAL(0));
|
||||
ObjectTypeDB::bind_method(_MD("get_recognized_extensions","type"),&_ResourceSaver::get_recognized_extensions);
|
||||
|
||||
BIND_CONSTANT(FLAG_RELATIVE_PATHS);
|
||||
BIND_CONSTANT(FLAG_BUNDLE_RESOURCES);
|
||||
BIND_CONSTANT(FLAG_CHANGE_PATH);
|
||||
BIND_CONSTANT(FLAG_OMIT_EDITOR_PROPERTIES);
|
||||
BIND_CONSTANT(FLAG_SAVE_BIG_ENDIAN);
|
||||
BIND_CONSTANT(FLAG_COMPRESS);
|
||||
}
|
||||
|
||||
_ResourceSaver::_ResourceSaver() {
|
||||
|
|
|
@ -39,6 +39,16 @@ protected:
|
|||
static _ResourceSaver *singleton;
|
||||
public:
|
||||
|
||||
enum SaverFlags {
|
||||
|
||||
FLAG_RELATIVE_PATHS=1,
|
||||
FLAG_BUNDLE_RESOURCES=2,
|
||||
FLAG_CHANGE_PATH=4,
|
||||
FLAG_OMIT_EDITOR_PROPERTIES=8,
|
||||
FLAG_SAVE_BIG_ENDIAN=16,
|
||||
FLAG_COMPRESS=32,
|
||||
};
|
||||
|
||||
static _ResourceSaver *get_singleton() { return singleton; }
|
||||
|
||||
Error save(const String &p_path,const RES& p_resource, uint32_t p_flags);
|
||||
|
|
|
@ -1660,6 +1660,31 @@ void Image::set_compress_bc_func(void (*p_compress_func)(Image *)) {
|
|||
}
|
||||
|
||||
|
||||
|
||||
void Image::premultiply_alpha() {
|
||||
|
||||
if (data.size()==0)
|
||||
return;
|
||||
|
||||
if (format!=FORMAT_RGBA)
|
||||
return; //not needed
|
||||
|
||||
DVector<uint8_t>::Write wp = data.write();
|
||||
unsigned char *data_ptr=wp.ptr();
|
||||
|
||||
|
||||
for(int i=0;i<height;i++) {
|
||||
for(int j=0;j<width;j++) {
|
||||
|
||||
BColor bc = _get_pixel(j,i,data_ptr,0);
|
||||
bc.r=(int(bc.r)*int(bc.a))>>8;
|
||||
bc.g=(int(bc.g)*int(bc.a))>>8;
|
||||
bc.b=(int(bc.b)*int(bc.a))>>8;
|
||||
_put_pixel(j,i,bc,data_ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Image::fix_alpha_edges() {
|
||||
|
||||
if (data.size()==0)
|
||||
|
|
|
@ -320,6 +320,7 @@ public:
|
|||
void decompress();
|
||||
|
||||
void fix_alpha_edges();
|
||||
void premultiply_alpha();
|
||||
|
||||
void blit_rect(const Image& p_src, const Rect2& p_src_rect,const Point2& p_dest);
|
||||
void brush_transfer(const Image& p_src, const Image& p_brush, const Point2& p_dest);
|
||||
|
|
|
@ -25,6 +25,7 @@ Error FileAccessEncrypted::open_and_parse(FileAccess *p_base,const Vector<uint8_
|
|||
|
||||
} else if (p_mode==MODE_READ) {
|
||||
|
||||
writing=false;
|
||||
key=p_key;
|
||||
uint32_t magic = p_base->get_32();
|
||||
print_line("MAGIC: "+itos(magic));
|
||||
|
@ -278,6 +279,10 @@ uint64_t FileAccessEncrypted::_get_modified_time(const String& p_file){
|
|||
FileAccessEncrypted::FileAccessEncrypted() {
|
||||
|
||||
file=NULL;
|
||||
pos=0;
|
||||
eofed=false;
|
||||
mode=MODE_MAX;
|
||||
writing=false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -188,6 +188,18 @@ void IP::erase_resolve_item(ResolverID p_id) {
|
|||
}
|
||||
|
||||
|
||||
Array IP::_get_local_addresses() const {
|
||||
|
||||
Array addresses;
|
||||
List<IP_Address> ip_addresses;
|
||||
get_local_addresses(&ip_addresses);
|
||||
for(List<IP_Address>::Element *E=ip_addresses.front();E;E=E->next()) {
|
||||
addresses.push_back(E->get());
|
||||
}
|
||||
|
||||
return addresses;
|
||||
}
|
||||
|
||||
void IP::_bind_methods() {
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("resolve_hostname","host"),&IP::resolve_hostname);
|
||||
|
@ -195,6 +207,7 @@ void IP::_bind_methods() {
|
|||
ObjectTypeDB::bind_method(_MD("get_resolve_item_status","id"),&IP::get_resolve_item_status);
|
||||
ObjectTypeDB::bind_method(_MD("get_resolve_item_address","id"),&IP::get_resolve_item_address);
|
||||
ObjectTypeDB::bind_method(_MD("erase_resolve_item","id"),&IP::erase_resolve_item);
|
||||
ObjectTypeDB::bind_method(_MD("get_local_addresses"),&IP::_get_local_addresses);
|
||||
|
||||
BIND_CONSTANT( RESOLVER_STATUS_NONE );
|
||||
BIND_CONSTANT( RESOLVER_STATUS_WAITING );
|
||||
|
|
|
@ -66,16 +66,19 @@ protected:
|
|||
static void _bind_methods();
|
||||
|
||||
virtual IP_Address _resolve_hostname(const String& p_hostname)=0;
|
||||
Array _get_local_addresses() const;
|
||||
|
||||
static IP* (*_create)();
|
||||
public:
|
||||
|
||||
|
||||
|
||||
IP_Address resolve_hostname(const String& p_hostname);
|
||||
// async resolver hostname
|
||||
ResolverID resolve_hostname_queue_item(const String& p_hostname);
|
||||
ResolverStatus get_resolve_item_status(ResolverID p_id) const;
|
||||
IP_Address get_resolve_item_address(ResolverID p_id) const;
|
||||
virtual void get_local_addresses(List<IP_Address> *r_addresses) const=0;
|
||||
void erase_resolve_item(ResolverID p_id);
|
||||
|
||||
static IP* get_singleton();
|
||||
|
|
|
@ -100,7 +100,7 @@ FileAccess *FileAccess::open(const String& p_path, int p_mode_flags, Error *r_er
|
|||
FileAccess *ret=NULL;
|
||||
if (!(p_mode_flags&WRITE) && PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled()) {
|
||||
ret = PackedData::get_singleton()->try_open_path(p_path);
|
||||
if (ret) {
|
||||
if (ret) {
|
||||
if (r_error)
|
||||
*r_error=OK;
|
||||
return ret;
|
||||
|
|
|
@ -211,6 +211,8 @@ void InputDefault::parse_input_event(const InputEvent& p_event) {
|
|||
if (p_event.key.scancode==0)
|
||||
break;
|
||||
|
||||
// print_line(p_event);
|
||||
|
||||
if (p_event.key.pressed)
|
||||
keys_pressed.insert(p_event.key.scancode);
|
||||
else
|
||||
|
|
|
@ -37,7 +37,7 @@ void MainLoop::_bind_methods() {
|
|||
BIND_CONSTANT(NOTIFICATION_WM_FOCUS_OUT);
|
||||
BIND_CONSTANT(NOTIFICATION_WM_QUIT_REQUEST);
|
||||
BIND_CONSTANT(NOTIFICATION_WM_UNFOCUS_REQUEST);
|
||||
|
||||
BIND_CONSTANT(NOTIFICATION_OS_MEMORY_WARNING);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -141,6 +141,7 @@ public:
|
|||
virtual int find_function(const String& p_function,const String& p_code) const=0;
|
||||
virtual String make_function(const String& p_class,const String& p_name,const StringArray& p_args) const=0;
|
||||
virtual Error complete_keyword(const String& p_code, int p_line, const String& p_base_path, const String& p_keyword, List<String>* r_options) { return ERR_UNAVAILABLE; }
|
||||
virtual void auto_indent_code(String& p_code,int p_from_line,int p_to_line) const=0;
|
||||
|
||||
/* DEBUGGER FUNCTIONS */
|
||||
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
<ext_resource path="res://music.ogg" type="AudioStream"></ext_resource>
|
||||
<ext_resource path="res://tileset.xml" type="TileSet"></ext_resource>
|
||||
<ext_resource path="res://coin.xml" type="PackedScene"></ext_resource>
|
||||
<ext_resource path="res://player.xml" type="PackedScene"></ext_resource>
|
||||
<ext_resource path="res://moving_platform.xml" type="PackedScene"></ext_resource>
|
||||
<ext_resource path="res://seesaw.xml" type="PackedScene"></ext_resource>
|
||||
<ext_resource path="res://enemy.xml" type="PackedScene"></ext_resource>
|
||||
<ext_resource path="res://moving_platform.xml" type="PackedScene"></ext_resource>
|
||||
<ext_resource path="res://player.xml" type="PackedScene"></ext_resource>
|
||||
<ext_resource path="res://parallax_bg.xml" type="PackedScene"></ext_resource>
|
||||
<main_resource>
|
||||
<dictionary name="_bundled" shared="false">
|
||||
|
@ -160,9 +160,13 @@
|
|||
<string> "pixel_snap" </string>
|
||||
<bool> False </bool>
|
||||
<string> "zoom" </string>
|
||||
<real> 0.735092 </real>
|
||||
<real> 0.54036 </real>
|
||||
<string> "use_snap" </string>
|
||||
<bool> False </bool>
|
||||
<string> "ofs" </string>
|
||||
<vector2> 55.9232, 767.661 </vector2>
|
||||
<vector2> 418.81, 615.088 </vector2>
|
||||
<string> "snap" </string>
|
||||
<int> 10 </int>
|
||||
</dictionary>
|
||||
<string> "3D" </string>
|
||||
<dictionary shared="false">
|
||||
|
|
|
@ -6436,7 +6436,10 @@ void RasterizerGLES2::canvas_set_blend_mode(VS::MaterialBlendMode p_mode) {
|
|||
case VS::MATERIAL_BLEND_MODE_MUL: {
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
} break;
|
||||
case VS::MATERIAL_BLEND_MODE_PREMULT_ALPHA: {
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);
|
||||
} break;
|
||||
|
||||
}
|
||||
|
|
|
@ -64,6 +64,9 @@ void main() {
|
|||
highp float enc32 = dot( color,highp vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1) );
|
||||
color = vec4(vec3(enc32),1.0);
|
||||
#endif
|
||||
|
||||
// color.rgb*=color.a;
|
||||
gl_FragColor = color;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -30,12 +30,24 @@
|
|||
|
||||
#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED)
|
||||
|
||||
|
||||
#ifdef WINDOWS_ENABLED
|
||||
#define WINVER 0x0600
|
||||
#include <ws2tcpip.h>
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <iphlpapi.h>
|
||||
#else
|
||||
#include <netdb.h>
|
||||
#ifdef ANDROID_ENABLED
|
||||
#include "platform/android/ifaddrs_android.h"
|
||||
#else
|
||||
#include <ifaddrs.h>
|
||||
#endif
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#endif
|
||||
IP_Address IP_Unix::_resolve_hostname(const String& p_hostname) {
|
||||
|
||||
|
@ -52,6 +64,93 @@ IP_Address IP_Unix::_resolve_hostname(const String& p_hostname) {
|
|||
|
||||
}
|
||||
|
||||
#if defined(WINDOWS_ENABLED)
|
||||
|
||||
void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const {
|
||||
|
||||
ULONG buf_size = 1024;
|
||||
IP_ADAPTER_ADDRESSES* addrs;
|
||||
|
||||
while (true) {
|
||||
|
||||
addrs = (IP_ADAPTER_ADDRESSES*)memalloc(buf_size);
|
||||
int err = GetAdaptersAddresses(AF_INET, GAA_FLAG_SKIP_ANYCAST |
|
||||
GAA_FLAG_SKIP_MULTICAST |
|
||||
GAA_FLAG_SKIP_DNS_SERVER |
|
||||
GAA_FLAG_SKIP_FRIENDLY_NAME,
|
||||
NULL, addrs, &buf_size);
|
||||
if (err == NO_ERROR) {
|
||||
break;
|
||||
};
|
||||
memfree(addrs);
|
||||
if (err == ERROR_BUFFER_OVERFLOW) {
|
||||
continue; // will go back and alloc the right size
|
||||
};
|
||||
|
||||
ERR_EXPLAIN("Call to GetAdaptersAddresses failed with error " + itos(err));
|
||||
ERR_FAIL();
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
IP_ADAPTER_ADDRESSES* adapter = addrs;
|
||||
|
||||
while (adapter != NULL) {
|
||||
|
||||
IP_ADAPTER_UNICAST_ADDRESS* address = adapter->FirstUnicastAddress;
|
||||
while (address != NULL) {
|
||||
|
||||
char addr_chr[INET_ADDRSTRLEN];
|
||||
SOCKADDR_IN* ipv4 = reinterpret_cast<SOCKADDR_IN*>(address->Address.lpSockaddr);
|
||||
|
||||
IP_Address ip;
|
||||
ip.host= *((unsigned long*)&ipv4->sin_addr);
|
||||
|
||||
|
||||
//inet_ntop(AF_INET, &ipv4->sin_addr, addr_chr, INET_ADDRSTRLEN);
|
||||
|
||||
r_addresses->push_back(ip);
|
||||
|
||||
address = address->Next;
|
||||
};
|
||||
adapter = adapter->Next;
|
||||
};
|
||||
|
||||
memfree(addrs);
|
||||
};
|
||||
|
||||
|
||||
#else
|
||||
|
||||
void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const {
|
||||
|
||||
struct ifaddrs * ifAddrStruct=NULL;
|
||||
struct ifaddrs * ifa=NULL;
|
||||
|
||||
getifaddrs(&ifAddrStruct);
|
||||
|
||||
for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) {
|
||||
if (ifa ->ifa_addr->sa_family==AF_INET) { // check it is IP4
|
||||
// is a valid IP4 Address
|
||||
|
||||
IP_Address ip;
|
||||
ip.host= *((unsigned long*)&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr);
|
||||
|
||||
r_addresses->push_back(ip);
|
||||
}/* else if (ifa->ifa_addr->sa_family==AF_INET6) { // check it is IP6
|
||||
// is a valid IP6 Address
|
||||
tmpAddrPtr=&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
|
||||
char addressBuffer[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
|
||||
printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer);
|
||||
} */
|
||||
}
|
||||
|
||||
if (ifAddrStruct!=NULL) freeifaddrs(ifAddrStruct);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
void IP_Unix::make_default() {
|
||||
|
||||
_create=_create_unix;
|
||||
|
|
|
@ -41,6 +41,8 @@ class IP_Unix : public IP {
|
|||
static IP* _create_unix();
|
||||
public:
|
||||
|
||||
virtual void get_local_addresses(List<IP_Address> *r_addresses) const;
|
||||
|
||||
static void make_default();
|
||||
IP_Unix();
|
||||
};
|
||||
|
|
|
@ -1263,6 +1263,16 @@ Error GDCompiler::_parse_function(GDScript *p_script,const GDParser::ClassNode *
|
|||
gdfunc->name=func_name;
|
||||
gdfunc->_script=p_script;
|
||||
gdfunc->source=source;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
|
||||
{
|
||||
gdfunc->func_cname=(String(source)+" - "+String(func_name)).utf8();
|
||||
gdfunc->_func_cname=gdfunc->func_cname.get_data();
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
if (p_func) {
|
||||
gdfunc->_initial_line=p_func->line;
|
||||
} else {
|
||||
|
|
|
@ -787,3 +787,67 @@ Error GDScriptLanguage::complete_keyword(const String& p_code, int p_line, const
|
|||
return OK;
|
||||
}
|
||||
|
||||
void GDScriptLanguage::auto_indent_code(String& p_code,int p_from_line,int p_to_line) const {
|
||||
|
||||
|
||||
Vector<String> lines = p_code.split("\n");
|
||||
List<int> indent_stack;
|
||||
|
||||
for(int i=0;i<lines.size();i++) {
|
||||
|
||||
String l = lines[i];
|
||||
int tc=0;
|
||||
for(int j=0;j<l.length();j++) {
|
||||
if (l[j]==' ' || l[j]=='\t') {
|
||||
|
||||
tc++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String st = l.substr(tc,l.length()).strip_edges();
|
||||
if (st=="" || st.begins_with("#"))
|
||||
continue; //ignore!
|
||||
|
||||
int ilevel=0;
|
||||
if (indent_stack.size()) {
|
||||
ilevel=indent_stack.back()->get();
|
||||
}
|
||||
|
||||
if (tc>ilevel) {
|
||||
indent_stack.push_back(tc);
|
||||
} else if (tc<ilevel) {
|
||||
while(indent_stack.size() && indent_stack.back()->get()>tc) {
|
||||
indent_stack.pop_back();
|
||||
}
|
||||
|
||||
if (indent_stack.size() && indent_stack.back()->get()!=tc)
|
||||
indent_stack.push_back(tc); //this is not right but gets the job done
|
||||
}
|
||||
|
||||
if (i>=p_from_line) {
|
||||
|
||||
l="";
|
||||
for(int j=0;j<indent_stack.size();j++)
|
||||
l+="\t";
|
||||
l+=st;
|
||||
|
||||
|
||||
} else if (i>p_to_line) {
|
||||
break;
|
||||
}
|
||||
|
||||
//print_line(itos(indent_stack.size())+","+itos(tc)+": "+l);
|
||||
lines[i]=l;
|
||||
}
|
||||
|
||||
p_code="";
|
||||
for(int i=0;i<lines.size();i++) {
|
||||
if (i>0)
|
||||
p_code+="\n";
|
||||
p_code+=lines[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1221,6 +1221,15 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
|
|||
return; //go back a level
|
||||
}
|
||||
|
||||
if (pending_newline!=-1) {
|
||||
|
||||
NewLineNode *nl = alloc_node<NewLineNode>();
|
||||
nl->line=pending_newline;
|
||||
p_block->statements.push_back(nl);
|
||||
pending_newline=-1;
|
||||
|
||||
}
|
||||
|
||||
switch(token) {
|
||||
|
||||
|
||||
|
@ -1234,16 +1243,19 @@ void GDParser::_parse_block(BlockNode *p_block,bool p_static) {
|
|||
} break;
|
||||
case GDTokenizer::TK_NEWLINE: {
|
||||
|
||||
if (!_parse_newline()) {
|
||||
if (!error_set) {
|
||||
p_block->end_line=tokenizer->get_token_line();
|
||||
pending_newline=p_block->end_line;
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NewLineNode *nl = alloc_node<NewLineNode>();
|
||||
nl->line=tokenizer->get_token_line();
|
||||
p_block->statements.push_back(nl);
|
||||
|
||||
if (!_parse_newline()) {
|
||||
if (!error_set) {
|
||||
p_block->end_line=tokenizer->get_token_line();
|
||||
}
|
||||
return;
|
||||
}
|
||||
} break;
|
||||
case GDTokenizer::TK_CF_PASS: {
|
||||
if (tokenizer->get_token(1)!=GDTokenizer::TK_SEMICOLON && tokenizer->get_token(1)!=GDTokenizer::TK_NEWLINE ) {
|
||||
|
@ -1782,6 +1794,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
|
|||
case GDTokenizer::TK_PR_FUNCTION: {
|
||||
|
||||
bool _static=false;
|
||||
pending_newline=-1;
|
||||
|
||||
if (tokenizer->get_token(-1)==GDTokenizer::TK_PR_STATIC) {
|
||||
|
||||
|
@ -2490,6 +2503,7 @@ void GDParser::clear() {
|
|||
tab_level.push_back(0);
|
||||
error_line=0;
|
||||
error_column=0;
|
||||
pending_newline=-1;
|
||||
parenthesis=0;
|
||||
current_export.type=Variant::NIL;
|
||||
error="";
|
||||
|
@ -2501,6 +2515,7 @@ GDParser::GDParser() {
|
|||
head=NULL;
|
||||
list=NULL;
|
||||
tokenizer=NULL;
|
||||
pending_newline=-1;
|
||||
clear();
|
||||
|
||||
}
|
||||
|
|
|
@ -362,6 +362,8 @@ private:
|
|||
int error_line;
|
||||
int error_column;
|
||||
|
||||
int pending_newline;
|
||||
|
||||
List<int> tab_level;
|
||||
|
||||
String base_path;
|
||||
|
|
|
@ -1159,6 +1159,9 @@ GDFunction::GDFunction() {
|
|||
_stack_size=0;
|
||||
_call_size=0;
|
||||
name="<anonymous>";
|
||||
#ifdef DEBUG_ENABLED
|
||||
_func_cname=NULL;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -118,10 +118,13 @@ friend class GDCompiler;
|
|||
Vector<Variant> constants;
|
||||
Vector<StringName> global_names;
|
||||
Vector<int> default_arguments;
|
||||
|
||||
Vector<int> code;
|
||||
#ifdef DEBUG_ENABLED
|
||||
CharString func_cname;
|
||||
const char*_func_cname;
|
||||
#endif
|
||||
|
||||
List<StackDebug> stack_debug;
|
||||
List<StackDebug> stack_debug;
|
||||
|
||||
_FORCE_INLINE_ Variant *_get_variant(int p_address,GDInstance *p_instance,GDScript *p_script,Variant &self,Variant *p_stack,String& r_error) const;
|
||||
_FORCE_INLINE_ String _get_call_error(const Variant::CallError& p_err, const String& p_where,const Variant**argptrs) const;
|
||||
|
@ -427,6 +430,7 @@ public:
|
|||
virtual int find_function(const String& p_function,const String& p_code) const;
|
||||
virtual String make_function(const String& p_class,const String& p_name,const StringArray& p_args) const;
|
||||
virtual Error complete_keyword(const String& p_code, int p_line, const String& p_base_path,const String& p_keyword, List<String>* r_options);
|
||||
virtual void auto_indent_code(String& p_code,int p_from_line,int p_to_line) const;
|
||||
|
||||
/* DEBUGGER FUNCTIONS */
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ android_files = [
|
|||
'dir_access_jandroid.cpp',
|
||||
'thread_jandroid.cpp',
|
||||
'audio_driver_jandroid.cpp',
|
||||
'ifaddrs_android.cpp',
|
||||
'android_native_app_glue.c',
|
||||
'java_glue.cpp'
|
||||
]
|
||||
|
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* libjingle
|
||||
* Copyright 2012, Google Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "ifaddrs_android.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <net/if.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
struct netlinkrequest {
|
||||
nlmsghdr header;
|
||||
ifaddrmsg msg;
|
||||
};
|
||||
namespace {
|
||||
const int kMaxReadSize = 4096;
|
||||
};
|
||||
static int set_ifname(struct ifaddrs* ifaddr, int interface) {
|
||||
char buf[IFNAMSIZ] = {0};
|
||||
char* name = if_indextoname(interface, buf);
|
||||
if (name == NULL) {
|
||||
return -1;
|
||||
}
|
||||
ifaddr->ifa_name = new char[strlen(name) + 1];
|
||||
strncpy(ifaddr->ifa_name, name, strlen(name) + 1);
|
||||
return 0;
|
||||
}
|
||||
static int set_flags(struct ifaddrs* ifaddr) {
|
||||
int fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (fd == -1) {
|
||||
return -1;
|
||||
}
|
||||
ifreq ifr;
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strncpy(ifr.ifr_name, ifaddr->ifa_name, IFNAMSIZ - 1);
|
||||
int rc = ioctl(fd, SIOCGIFFLAGS, &ifr);
|
||||
close(fd);
|
||||
if (rc == -1) {
|
||||
return -1;
|
||||
}
|
||||
ifaddr->ifa_flags = ifr.ifr_flags;
|
||||
return 0;
|
||||
}
|
||||
static int set_addresses(struct ifaddrs* ifaddr, ifaddrmsg* msg, void* data,
|
||||
size_t len) {
|
||||
if (msg->ifa_family == AF_INET) {
|
||||
sockaddr_in* sa = new sockaddr_in;
|
||||
sa->sin_family = AF_INET;
|
||||
memcpy(&sa->sin_addr, data, len);
|
||||
ifaddr->ifa_addr = reinterpret_cast<sockaddr*>(sa);
|
||||
} else if (msg->ifa_family == AF_INET6) {
|
||||
sockaddr_in6* sa = new sockaddr_in6;
|
||||
sa->sin6_family = AF_INET6;
|
||||
sa->sin6_scope_id = msg->ifa_index;
|
||||
memcpy(&sa->sin6_addr, data, len);
|
||||
ifaddr->ifa_addr = reinterpret_cast<sockaddr*>(sa);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int make_prefixes(struct ifaddrs* ifaddr, int family, int prefixlen) {
|
||||
char* prefix = NULL;
|
||||
if (family == AF_INET) {
|
||||
sockaddr_in* mask = new sockaddr_in;
|
||||
mask->sin_family = AF_INET;
|
||||
memset(&mask->sin_addr, 0, sizeof(in_addr));
|
||||
ifaddr->ifa_netmask = reinterpret_cast<sockaddr*>(mask);
|
||||
if (prefixlen > 32) {
|
||||
prefixlen = 32;
|
||||
}
|
||||
prefix = reinterpret_cast<char*>(&mask->sin_addr);
|
||||
} else if (family == AF_INET6) {
|
||||
sockaddr_in6* mask = new sockaddr_in6;
|
||||
mask->sin6_family = AF_INET6;
|
||||
memset(&mask->sin6_addr, 0, sizeof(in6_addr));
|
||||
ifaddr->ifa_netmask = reinterpret_cast<sockaddr*>(mask);
|
||||
if (prefixlen > 128) {
|
||||
prefixlen = 128;
|
||||
}
|
||||
prefix = reinterpret_cast<char*>(&mask->sin6_addr);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
for (int i = 0; i < (prefixlen / 8); i++) {
|
||||
*prefix++ = 0xFF;
|
||||
}
|
||||
char remainder = 0xff;
|
||||
remainder <<= (8 - prefixlen % 8);
|
||||
*prefix = remainder;
|
||||
return 0;
|
||||
}
|
||||
static int populate_ifaddrs(struct ifaddrs* ifaddr, ifaddrmsg* msg, void* bytes,
|
||||
size_t len) {
|
||||
if (set_ifname(ifaddr, msg->ifa_index) != 0) {
|
||||
return -1;
|
||||
}
|
||||
if (set_flags(ifaddr) != 0) {
|
||||
return -1;
|
||||
}
|
||||
if (set_addresses(ifaddr, msg, bytes, len) != 0) {
|
||||
return -1;
|
||||
}
|
||||
if (make_prefixes(ifaddr, msg->ifa_family, msg->ifa_prefixlen) != 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int getifaddrs(struct ifaddrs** result) {
|
||||
int fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
if (fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
netlinkrequest ifaddr_request;
|
||||
memset(&ifaddr_request, 0, sizeof(ifaddr_request));
|
||||
ifaddr_request.header.nlmsg_flags = NLM_F_ROOT | NLM_F_REQUEST;
|
||||
ifaddr_request.header.nlmsg_type = RTM_GETADDR;
|
||||
ifaddr_request.header.nlmsg_len = NLMSG_LENGTH(sizeof(ifaddrmsg));
|
||||
ssize_t count = send(fd, &ifaddr_request, ifaddr_request.header.nlmsg_len, 0);
|
||||
if (static_cast<size_t>(count) != ifaddr_request.header.nlmsg_len) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
struct ifaddrs* start = NULL;
|
||||
struct ifaddrs* current = NULL;
|
||||
char buf[kMaxReadSize];
|
||||
ssize_t amount_read = recv(fd, &buf, kMaxReadSize, 0);
|
||||
while (amount_read > 0) {
|
||||
nlmsghdr* header = reinterpret_cast<nlmsghdr*>(&buf[0]);
|
||||
size_t header_size = static_cast<size_t>(amount_read);
|
||||
for ( ; NLMSG_OK(header, header_size);
|
||||
header = NLMSG_NEXT(header, header_size)) {
|
||||
switch (header->nlmsg_type) {
|
||||
case NLMSG_DONE:
|
||||
// Success. Return.
|
||||
*result = start;
|
||||
close(fd);
|
||||
return 0;
|
||||
case NLMSG_ERROR:
|
||||
close(fd);
|
||||
freeifaddrs(start);
|
||||
return -1;
|
||||
case RTM_NEWADDR: {
|
||||
ifaddrmsg* address_msg =
|
||||
reinterpret_cast<ifaddrmsg*>(NLMSG_DATA(header));
|
||||
rtattr* rta = IFA_RTA(address_msg);
|
||||
ssize_t payload_len = IFA_PAYLOAD(header);
|
||||
while (RTA_OK(rta, payload_len)) {
|
||||
if (rta->rta_type == IFA_ADDRESS) {
|
||||
int family = address_msg->ifa_family;
|
||||
if (family == AF_INET || family == AF_INET6) {
|
||||
ifaddrs* newest = new ifaddrs;
|
||||
memset(newest, 0, sizeof(ifaddrs));
|
||||
if (current) {
|
||||
current->ifa_next = newest;
|
||||
} else {
|
||||
start = newest;
|
||||
}
|
||||
if (populate_ifaddrs(newest, address_msg, RTA_DATA(rta),
|
||||
RTA_PAYLOAD(rta)) != 0) {
|
||||
freeifaddrs(start);
|
||||
*result = NULL;
|
||||
return -1;
|
||||
}
|
||||
current = newest;
|
||||
}
|
||||
}
|
||||
rta = RTA_NEXT(rta, payload_len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
amount_read = recv(fd, &buf, kMaxReadSize, 0);
|
||||
}
|
||||
close(fd);
|
||||
freeifaddrs(start);
|
||||
return -1;
|
||||
}
|
||||
void freeifaddrs(struct ifaddrs* addrs) {
|
||||
struct ifaddrs* last = NULL;
|
||||
struct ifaddrs* cursor = addrs;
|
||||
while (cursor) {
|
||||
delete[] cursor->ifa_name;
|
||||
delete cursor->ifa_addr;
|
||||
delete cursor->ifa_netmask;
|
||||
last = cursor;
|
||||
cursor = cursor->ifa_next;
|
||||
delete last;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* libjingle
|
||||
* Copyright 2013, Google Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef TALK_BASE_IFADDRS_ANDROID_H_
|
||||
#define TALK_BASE_IFADDRS_ANDROID_H_
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
// Implementation of getifaddrs for Android.
|
||||
// Fills out a list of ifaddr structs (see below) which contain information
|
||||
// about every network interface available on the host.
|
||||
// See 'man getifaddrs' on Linux or OS X (nb: it is not a POSIX function).
|
||||
struct ifaddrs {
|
||||
struct ifaddrs* ifa_next;
|
||||
char* ifa_name;
|
||||
unsigned int ifa_flags;
|
||||
struct sockaddr* ifa_addr;
|
||||
struct sockaddr* ifa_netmask;
|
||||
// Real ifaddrs has broadcast, point to point and data members.
|
||||
// We don't need them (yet?).
|
||||
};
|
||||
int getifaddrs(struct ifaddrs** result);
|
||||
void freeifaddrs(struct ifaddrs* addrs);
|
||||
#endif // TALK_BASE_IFADDRS_ANDROID_H_
|
|
@ -65,6 +65,9 @@ import java.io.InputStream;
|
|||
|
||||
public class Godot extends Activity implements SensorEventListener
|
||||
{
|
||||
|
||||
static final int MAX_SINGLETONS = 64;
|
||||
|
||||
static public class SingletonBase {
|
||||
|
||||
protected void registerClass(String p_name, String[] p_methods) {
|
||||
|
@ -104,8 +107,21 @@ public class Godot extends Activity implements SensorEventListener
|
|||
|
||||
|
||||
}
|
||||
|
||||
Godot.singletons[Godot.singleton_count++]=this;
|
||||
}
|
||||
|
||||
protected void onMainActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
protected void onMainResume() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void registerMethods() {}
|
||||
}
|
||||
|
||||
|
@ -133,6 +149,12 @@ public class Godot extends Activity implements SensorEventListener
|
|||
//setTitle(title);
|
||||
}
|
||||
|
||||
|
||||
static SingletonBase singletons[] = new SingletonBase[MAX_SINGLETONS];
|
||||
static int singleton_count=0;
|
||||
|
||||
|
||||
|
||||
public interface ResultCallback {
|
||||
public void callback(int requestCode, int resultCode, Intent data);
|
||||
};
|
||||
|
@ -147,6 +169,11 @@ public class Godot extends Activity implements SensorEventListener
|
|||
result_callback.callback(requestCode, resultCode, data);
|
||||
result_callback = null;
|
||||
};
|
||||
|
||||
for(int i=0;i<singleton_count;i++) {
|
||||
|
||||
singletons[i].onMainActivityResult(requestCode,resultCode,data);
|
||||
}
|
||||
};
|
||||
|
||||
public void onVideoInit(boolean use_gl2) {
|
||||
|
@ -271,6 +298,12 @@ public class Godot extends Activity implements SensorEventListener
|
|||
mView.onResume();
|
||||
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
|
||||
GodotLib.focusin();
|
||||
|
||||
for(int i=0;i<singleton_count;i++) {
|
||||
|
||||
singletons[i].onMainResume();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override public void onSensorChanged(SensorEvent event) {
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package com.android.godot;
|
||||
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.util.Log;
|
||||
|
||||
|
||||
public class GodotPaymentV3 extends Godot.SingletonBase {
|
||||
|
@ -13,14 +16,17 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
|
|||
private String accessToken;
|
||||
|
||||
private String purchaseValidationUrlPrefix;
|
||||
|
||||
private String transactionId;
|
||||
|
||||
public void purchase( String _sku) {
|
||||
public void purchase( String _sku, String _transactionId) {
|
||||
final String sku = _sku;
|
||||
final String transactionId = _transactionId;
|
||||
activity.getPaymentsManager().setBaseSingleton(this);
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
activity.getPaymentsManager().requestPurchase(sku);
|
||||
activity.getPaymentsManager().requestPurchase(sku, transactionId);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -38,22 +44,31 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
|
|||
|
||||
public GodotPaymentV3(Activity p_activity) {
|
||||
|
||||
registerClass("GodotPayments", new String[] {"purchase", "setPurchaseCallbackId", "setPurchaseValidationUrlPrefix"});
|
||||
registerClass("GodotPayments", new String[] {"purchase", "setPurchaseCallbackId", "setPurchaseValidationUrlPrefix", "setTransactionId", "getSignature"});
|
||||
activity=(Godot) p_activity;
|
||||
}
|
||||
|
||||
|
||||
private String signature;
|
||||
public String getSignature(){
|
||||
return this.signature;
|
||||
}
|
||||
|
||||
public void callbackSuccess(String ticket){
|
||||
GodotLib.callobject(purchaseCallbackId, "purchase_success", new Object[]{ticket});
|
||||
|
||||
public void callbackSuccess(String ticket, String signature){
|
||||
Log.d(this.getClass().getName(), "PRE-Send callback to purchase success");
|
||||
GodotLib.calldeferred(purchaseCallbackId, "purchase_success", new Object[]{ticket, signature});
|
||||
Log.d(this.getClass().getName(), "POST-Send callback to purchase success");
|
||||
}
|
||||
|
||||
public void callbackFail(){
|
||||
GodotLib.callobject(purchaseCallbackId, "purchase_fail", new Object[]{});
|
||||
GodotLib.calldeferred(purchaseCallbackId, "purchase_fail", new Object[]{});
|
||||
// GodotLib.callobject(purchaseCallbackId, "purchase_fail", new Object[]{});
|
||||
}
|
||||
|
||||
public void callbackCancel(){
|
||||
GodotLib.callobject(purchaseCallbackId, "purchase_cancel", new Object[]{});
|
||||
GodotLib.calldeferred(purchaseCallbackId, "purchase_cancel", new Object[]{});
|
||||
// GodotLib.callobject(purchaseCallbackId, "purchase_cancel", new Object[]{});
|
||||
}
|
||||
|
||||
public int getPurchaseCallbackId() {
|
||||
|
@ -84,4 +99,12 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
|
|||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
public void setTransactionId(String transactionId){
|
||||
this.transactionId = transactionId;
|
||||
}
|
||||
|
||||
public String getTransactionId(){
|
||||
return this.transactionId;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -56,8 +56,7 @@ abstract public class ConsumeTask {
|
|||
|
||||
protected void onPostExecute(String param){
|
||||
if(param == null){
|
||||
|
||||
success(new PaymentsCache(context).getConsumableValue("ticket", sku));
|
||||
success( new PaymentsCache(context).getConsumableValue("ticket", sku) );
|
||||
}else{
|
||||
error(param);
|
||||
}
|
||||
|
|
|
@ -34,7 +34,8 @@ abstract public class HandlePurchaseTask {
|
|||
|
||||
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
|
||||
Log.d("XXX", "Purchase data:" + purchaseData);
|
||||
// String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
|
||||
String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
|
||||
Log.d("XXX", "Purchase signature:" + dataSignature);
|
||||
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
|
||||
|
@ -57,12 +58,13 @@ abstract public class HandlePurchaseTask {
|
|||
error("Untrusted callback");
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d("XXX", "Este es el product ID:" + productId);
|
||||
pc.setConsumableValue("ticket_signautre", productId, dataSignature);
|
||||
pc.setConsumableValue("ticket", productId, purchaseData);
|
||||
pc.setConsumableFlag("block", productId, true);
|
||||
pc.setConsumableValue("token", productId, purchaseToken);
|
||||
|
||||
success(productId);
|
||||
success(productId, dataSignature);
|
||||
return;
|
||||
} catch (JSONException e) {
|
||||
error(e.getMessage());
|
||||
|
@ -72,7 +74,7 @@ abstract public class HandlePurchaseTask {
|
|||
}
|
||||
}
|
||||
|
||||
abstract protected void success(String ticket);
|
||||
abstract protected void success(String ticket, String signature);
|
||||
abstract protected void error(String message);
|
||||
abstract protected void canceled();
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.android.godot.payments;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.util.Log;
|
||||
|
||||
public class PaymentsCache {
|
||||
|
||||
|
@ -30,12 +31,14 @@ public class PaymentsCache {
|
|||
SharedPreferences sharedPref = context.getSharedPreferences("consumables_" + set, Context.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = sharedPref.edit();
|
||||
editor.putString(sku, value);
|
||||
Log.d("XXX", "Setting asset: consumables_" + set + ":" + sku);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
public String getConsumableValue(String set, String sku){
|
||||
SharedPreferences sharedPref = context.getSharedPreferences(
|
||||
"consumables_" + set, Context.MODE_PRIVATE);
|
||||
Log.d("XXX", "Getting asset: consumables_" + set + ":" + sku);
|
||||
return sharedPref.getString(sku, null);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import android.content.Context;
|
|||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.godot.Godot;
|
||||
import com.android.godot.GodotPaymentV3;
|
||||
|
@ -63,7 +64,7 @@ public class PaymentsManager {
|
|||
}
|
||||
};
|
||||
|
||||
public void requestPurchase(String sku){
|
||||
public void requestPurchase(String sku, String transactionId){
|
||||
new PurchaseTask(mService, Godot.getInstance()) {
|
||||
|
||||
@Override
|
||||
|
@ -76,7 +77,7 @@ public class PaymentsManager {
|
|||
protected void canceled() {
|
||||
godotPaymentV3.callbackCancel();
|
||||
}
|
||||
}.purchase(sku);
|
||||
}.purchase(sku, transactionId);
|
||||
|
||||
}
|
||||
|
||||
|
@ -84,13 +85,14 @@ public class PaymentsManager {
|
|||
new HandlePurchaseTask(activity){
|
||||
|
||||
@Override
|
||||
protected void success(final String sku) {
|
||||
protected void success(final String sku, final String signature) {
|
||||
new ConsumeTask(mService, activity) {
|
||||
|
||||
@Override
|
||||
protected void success(String ticket) {
|
||||
// godotPaymentV3.callbackSuccess("");
|
||||
godotPaymentV3.callbackSuccess(ticket);
|
||||
Log.d("XXX", "calling success:" + signature);
|
||||
godotPaymentV3.callbackSuccess(ticket, signature);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -131,7 +133,7 @@ public class PaymentsManager {
|
|||
|
||||
@Override
|
||||
protected void success(String ticket) {
|
||||
godotPaymentV3.callbackSuccess(ticket);
|
||||
godotPaymentV3.callbackSuccess(ticket, null);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ abstract public class PurchaseTask {
|
|||
|
||||
private boolean isLooping = false;
|
||||
|
||||
public void purchase(final String sku){
|
||||
public void purchase(final String sku, final String transactionId){
|
||||
Log.d("XXX", "Starting purchase for: " + sku);
|
||||
PaymentsCache pc = new PaymentsCache(context);
|
||||
Boolean isBlocked = pc.getConsumableFlag("block", sku);
|
||||
|
@ -40,7 +40,7 @@ abstract public class PurchaseTask {
|
|||
// error("Awaiting payment confirmation");
|
||||
// return;
|
||||
// }
|
||||
final String hash = Crypt.createRandomHash() + Crypt.createRandomHash();
|
||||
final String hash = transactionId;
|
||||
|
||||
Bundle buyIntentBundle;
|
||||
try {
|
||||
|
@ -76,7 +76,7 @@ abstract public class PurchaseTask {
|
|||
return;
|
||||
}
|
||||
isLooping=true;
|
||||
PurchaseTask.this.purchase(sku);
|
||||
PurchaseTask.this.purchase(sku, transactionId);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
jarsigner -digestalg SHA1 -sigalg MD5withRSA -verbose -keystore /home/luis/Downloads/carnavalguachin.keystore -storepass 12345678 "$1" momoselacome
|
||||
jarsigner -digestalg SHA1 -sigalg MD5withRSA -verbose -keystore my-release-key.keystore "$1" reduz
|
||||
|
||||
echo ""
|
||||
echo ""
|
||||
|
|
|
@ -21,7 +21,8 @@ def get_opts():
|
|||
return [
|
||||
('IPHONEPLATFORM', 'name of the iphone platform', 'iPhoneOS'),
|
||||
('IPHONEPATH', 'the path to iphone toolchain', '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain'),
|
||||
('IPHONESDK', 'path to the iphone SDK', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk/'),
|
||||
('IOS_SDK_VERSION', 'The SDK version', 'iPhoneOS7.0'),
|
||||
('IPHONESDK', 'path to the iphone SDK', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/${IOS_SDK_VERSION}.sdk/'),
|
||||
('game_center', 'Support for game center', 'yes'),
|
||||
('store_kit', 'Support for in-app store', 'yes'),
|
||||
('ios_gles22_override', 'Force GLES2.0 on iOS', 'yes'),
|
||||
|
@ -37,6 +38,7 @@ def get_flags():
|
|||
('tools', 'yes'),
|
||||
('nedmalloc', 'no'),
|
||||
('webp', 'yes'),
|
||||
('openssl','builtin'), #use builtin openssl
|
||||
]
|
||||
|
||||
|
||||
|
@ -81,7 +83,7 @@ def configure(env):
|
|||
'-framework', 'AudioToolbox',
|
||||
'-framework', 'SystemConfiguration',
|
||||
'-framework', 'Security',
|
||||
'-framework', 'AdSupport',
|
||||
#'-framework', 'AdSupport',
|
||||
'-framework', 'MediaPlayer',
|
||||
])
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ static String keyboard_text;
|
|||
static GLView* _instance = NULL;
|
||||
|
||||
static bool video_found_error = false;
|
||||
static bool video_playing = false;
|
||||
static float video_previous_volume = 0.0f;
|
||||
|
||||
void _show_keyboard(String p_existing) {
|
||||
|
@ -91,24 +92,29 @@ bool _play_video(String p_path, float p_volume) {
|
|||
[_instance addSubview:_instance.moviePlayerController.view];
|
||||
[_instance.moviePlayerController play];
|
||||
|
||||
video_playing = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _is_video_playing() {
|
||||
//NSInteger playback_state = _instance.moviePlayerController.playbackState;
|
||||
if (video_found_error)
|
||||
return false;
|
||||
return (_instance.moviePlayerController.playbackState == MPMoviePlaybackStatePlaying);
|
||||
return video_playing || _instance.moviePlayerController.playbackState == MPMoviePlaybackStatePlaying;
|
||||
//if (video_found_error)
|
||||
// return false;
|
||||
//return (_instance.moviePlayerController.playbackState == MPMoviePlaybackStatePlaying);
|
||||
}
|
||||
|
||||
void _pause_video() {
|
||||
[_instance.moviePlayerController pause];
|
||||
video_playing = false;
|
||||
}
|
||||
|
||||
void _stop_video() {
|
||||
[_instance.moviePlayerController stop];
|
||||
[_instance.moviePlayerController.view removeFromSuperview];
|
||||
[[MPMusicPlayerController applicationMusicPlayer] setVolume: video_previous_volume];
|
||||
video_playing = false;
|
||||
}
|
||||
|
||||
@implementation GLView
|
||||
|
@ -549,6 +555,7 @@ static void clear_touches() {
|
|||
[_instance.moviePlayerController.view removeFromSuperview];
|
||||
|
||||
[[MPMusicPlayerController applicationMusicPlayer] setVolume: video_previous_volume];
|
||||
video_playing = false;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -117,7 +117,7 @@ def configure(env):
|
|||
env.Append(CCFLAGS=['/DGLES2_ENABLED'])
|
||||
env.Append(CCFLAGS=['/DGLES1_ENABLED'])
|
||||
env.Append(CCFLAGS=['/DGLEW_ENABLED'])
|
||||
env.Append(LIBS=['winmm','opengl32','dsound','kernel32','ole32','user32','gdi32','wsock32', 'shell32','advapi32'])
|
||||
env.Append(LIBS=['winmm','opengl32','dsound','kernel32','ole32','user32','gdi32', 'IPHLPAPI', 'wsock32', 'shell32','advapi32'])
|
||||
|
||||
env.Append(LIBPATH=[os.getenv("WindowsSdkDir")+"/Lib"])
|
||||
if (os.getenv("DXSDK_DIR")):
|
||||
|
@ -196,7 +196,7 @@ def configure(env):
|
|||
env.Append(CCFLAGS=['-DWINDOWS_ENABLED','-mwindows'])
|
||||
env.Append(CPPFLAGS=['-DRTAUDIO_ENABLED'])
|
||||
env.Append(CCFLAGS=['-DGLES2_ENABLED','-DGLES1_ENABLED','-DGLEW_ENABLED'])
|
||||
env.Append(LIBS=['mingw32','opengl32', 'dsound', 'ole32', 'd3d9','winmm','gdi32','wsock32','kernel32'])
|
||||
env.Append(LIBS=['mingw32','opengl32', 'dsound', 'ole32', 'd3d9','winmm','gdi32','iphlpapi','wsock32','kernel32'])
|
||||
#'d3dx9d'
|
||||
env.Append(CPPFLAGS=['-DMINGW_ENABLED'])
|
||||
env.Append(LINKFLAGS=['-g'])
|
||||
|
|
|
@ -480,7 +480,7 @@ unsigned int OS_X11::get_mouse_button_state(unsigned int p_x11_state) {
|
|||
return state;
|
||||
}
|
||||
|
||||
void OS_X11::handle_key_event(XKeyEvent *p_event) {
|
||||
void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) {
|
||||
|
||||
|
||||
// X11 functions don't know what const is
|
||||
|
@ -591,17 +591,9 @@ void OS_X11::handle_key_event(XKeyEvent *p_event) {
|
|||
// To detect them, i use XPeekEvent and check that their
|
||||
// difference in time is below a treshold.
|
||||
|
||||
bool echo=false;
|
||||
|
||||
if (xkeyevent->type == KeyPress) {
|
||||
|
||||
// saved the time of the last keyrelease to see
|
||||
// if it's the same as this keypress.
|
||||
if (xkeyevent->time==last_keyrelease_time)
|
||||
echo=true;
|
||||
|
||||
} else {
|
||||
|
||||
if (xkeyevent->type != KeyPress) {
|
||||
|
||||
// make sure there are events pending,
|
||||
// so this call won't block.
|
||||
if (XPending(x11_display)>0) {
|
||||
|
@ -615,17 +607,21 @@ void OS_X11::handle_key_event(XKeyEvent *p_event) {
|
|||
// not very helpful today.
|
||||
|
||||
::Time tresh=ABS(peek_event.xkey.time-xkeyevent->time);
|
||||
if (peek_event.type == KeyPress && tresh<5 )
|
||||
echo=true;
|
||||
if (peek_event.type == KeyPress && tresh<5 ) {
|
||||
KeySym rk;
|
||||
nbytes=XLookupString((XKeyEvent*)&peek_event, str, 256, &rk, NULL);
|
||||
if (rk==keysym_keycode) {
|
||||
XEvent event;
|
||||
XNextEvent(x11_display, &event); //erase next event
|
||||
handle_key_event( (XKeyEvent*)&event,true );
|
||||
return; //ignore current, echo next
|
||||
}
|
||||
}
|
||||
|
||||
// use the time from peek_event so it always works
|
||||
last_keyrelease_time=peek_event.xkey.time;
|
||||
} else {
|
||||
last_keyrelease_time=xkeyevent->time;
|
||||
}
|
||||
|
||||
// save the time to check for echo when keypress happens
|
||||
|
||||
// save the time to check for echo when keypress happens
|
||||
}
|
||||
|
||||
|
||||
|
@ -643,7 +639,7 @@ void OS_X11::handle_key_event(XKeyEvent *p_event) {
|
|||
|
||||
event.key.scancode=keycode;
|
||||
event.key.unicode=unicode;
|
||||
event.key.echo=echo;
|
||||
event.key.echo=p_echo;
|
||||
|
||||
if (event.key.scancode==KEY_BACKTAB) {
|
||||
//make it consistent accross platforms.
|
||||
|
@ -1017,7 +1013,7 @@ String OS_X11::get_name() {
|
|||
|
||||
Error OS_X11::shell_open(String p_uri) {
|
||||
|
||||
|
||||
return ERR_UNAVAILABLE;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ class OS_X11 : public OS_Unix {
|
|||
MouseMode mouse_mode;
|
||||
Point2i center;
|
||||
|
||||
void handle_key_event(XKeyEvent *p_event);
|
||||
void handle_key_event(XKeyEvent *p_event,bool p_echo=false);
|
||||
void process_xevents();
|
||||
virtual void delete_main_loop();
|
||||
IP_Unix *ip_unix;
|
||||
|
|
|
@ -447,7 +447,7 @@ float CanvasItem::get_self_opacity() const {
|
|||
|
||||
void CanvasItem::set_blend_mode(BlendMode p_blend_mode) {
|
||||
|
||||
ERR_FAIL_INDEX(p_blend_mode,4);
|
||||
ERR_FAIL_INDEX(p_blend_mode,5);
|
||||
blend_mode=p_blend_mode;
|
||||
VisualServer::get_singleton()->canvas_item_set_blend_mode(canvas_item,VS::MaterialBlendMode(blend_mode));
|
||||
|
||||
|
@ -794,7 +794,7 @@ void CanvasItem::_bind_methods() {
|
|||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"visibility/behind_parent"), _SCS("set_draw_behind_parent"),_SCS("is_draw_behind_parent_enabled") );
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"visibility/on_top",PROPERTY_HINT_NONE,"",0), _SCS("_set_on_top"),_SCS("_is_on_top") ); //compatibility
|
||||
|
||||
ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"visibility/blend_mode",PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul"), _SCS("set_blend_mode"),_SCS("get_blend_mode") );
|
||||
ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"visibility/blend_mode",PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul,PMAlpha"), _SCS("set_blend_mode"),_SCS("get_blend_mode") );
|
||||
//exporting these two things doesn't really make much sense i think
|
||||
//ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transform/toplevel"), _SCS("set_as_toplevel"),_SCS("is_set_as_toplevel") );
|
||||
//ADD_PROPERTY(PropertyInfo(Variant::BOOL,"transform/notify"),_SCS("set_transform_notify"),_SCS("is_transform_notify_enabled"));
|
||||
|
@ -810,6 +810,7 @@ void CanvasItem::_bind_methods() {
|
|||
BIND_CONSTANT( BLEND_MODE_ADD );
|
||||
BIND_CONSTANT( BLEND_MODE_SUB );
|
||||
BIND_CONSTANT( BLEND_MODE_MUL );
|
||||
BIND_CONSTANT( BLEND_MODE_PREMULT_ALPHA );
|
||||
|
||||
|
||||
BIND_CONSTANT( NOTIFICATION_DRAW);
|
||||
|
|
|
@ -49,7 +49,8 @@ public:
|
|||
BLEND_MODE_MIX, //default
|
||||
BLEND_MODE_ADD,
|
||||
BLEND_MODE_SUB,
|
||||
BLEND_MODE_MUL
|
||||
BLEND_MODE_MUL,
|
||||
BLEND_MODE_PREMULT_ALPHA
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
|
@ -158,7 +158,7 @@ void Material::_bind_methods() {
|
|||
for(int i=0;i<HINT_MAX;i++)
|
||||
ADD_PROPERTYI( PropertyInfo( Variant::BOOL, String()+"hints/"+_hint_names[i] ),_SCS("set_hint"),_SCS("get_hint"),_hint_indices[i]);
|
||||
|
||||
ADD_PROPERTY( PropertyInfo( Variant::INT, "params/blend_mode",PROPERTY_HINT_ENUM,"Mix,Add,Sub" ), _SCS("set_blend_mode"),_SCS("get_blend_mode"));
|
||||
ADD_PROPERTY( PropertyInfo( Variant::INT, "params/blend_mode",PROPERTY_HINT_ENUM,"Mix,Add,Sub,PMAlpha" ), _SCS("set_blend_mode"),_SCS("get_blend_mode"));
|
||||
ADD_PROPERTY( PropertyInfo( Variant::REAL, "params/line_width",PROPERTY_HINT_RANGE,"0.1,32.0,0.1" ), _SCS("set_line_width"),_SCS("get_line_width"));
|
||||
|
||||
|
||||
|
@ -189,6 +189,8 @@ void Material::_bind_methods() {
|
|||
BIND_CONSTANT( BLEND_MODE_MIX );
|
||||
BIND_CONSTANT( BLEND_MODE_ADD );
|
||||
BIND_CONSTANT( BLEND_MODE_SUB );
|
||||
BIND_CONSTANT( BLEND_MODE_MUL );
|
||||
BIND_CONSTANT( BLEND_MODE_PREMULT_ALPHA );
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -75,6 +75,7 @@ public:
|
|||
BLEND_MODE_MUL = VS::MATERIAL_BLEND_MODE_MUL,
|
||||
BLEND_MODE_ADD = VS::MATERIAL_BLEND_MODE_ADD,
|
||||
BLEND_MODE_SUB = VS::MATERIAL_BLEND_MODE_SUB,
|
||||
BLEND_MODE_PREMULT_ALPHA = VS::MATERIAL_BLEND_MODE_PREMULT_ALPHA,
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -302,6 +302,16 @@ void ImageTexture::fix_alpha_edges() {
|
|||
}
|
||||
}
|
||||
|
||||
void ImageTexture::premultiply_alpha() {
|
||||
|
||||
if (format==Image::FORMAT_RGBA /*&& !(flags&FLAG_CUBEMAP)*/) {
|
||||
|
||||
Image img = get_data();
|
||||
img.premultiply_alpha();
|
||||
set_data(img);
|
||||
}
|
||||
}
|
||||
|
||||
bool ImageTexture::has_alpha() const {
|
||||
|
||||
return ( format==Image::FORMAT_GRAYSCALE_ALPHA || format==Image::FORMAT_INDEXED_ALPHA || format==Image::FORMAT_RGBA );
|
||||
|
@ -386,8 +396,10 @@ void ImageTexture::_bind_methods() {
|
|||
ObjectTypeDB::bind_method(_MD("set_lossy_storage_quality","quality"),&ImageTexture::set_lossy_storage_quality);
|
||||
ObjectTypeDB::bind_method(_MD("get_lossy_storage_quality"),&ImageTexture::get_lossy_storage_quality);
|
||||
ObjectTypeDB::bind_method(_MD("fix_alpha_edges"),&ImageTexture::fix_alpha_edges);
|
||||
ObjectTypeDB::bind_method(_MD("premultiply_alpha"),&ImageTexture::premultiply_alpha);
|
||||
ObjectTypeDB::bind_method(_MD("set_size_override","size"),&ImageTexture::set_size_override);
|
||||
ObjectTypeDB::set_method_flags(get_type_static(),_SCS("fix_alpha_edges"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
|
||||
ObjectTypeDB::set_method_flags(get_type_static(),_SCS("premultiply_alpha"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
|
||||
ObjectTypeDB::bind_method(_MD("_reload_hook","rid"),&ImageTexture::_reload_hook);
|
||||
|
||||
|
||||
|
|
|
@ -143,6 +143,7 @@ public:
|
|||
float get_lossy_storage_quality() const;
|
||||
|
||||
void fix_alpha_edges();
|
||||
void premultiply_alpha();
|
||||
|
||||
void set_size_override(const Size2& p_size);
|
||||
|
||||
|
|
|
@ -199,7 +199,8 @@ public:
|
|||
MATERIAL_BLEND_MODE_MIX, //default
|
||||
MATERIAL_BLEND_MODE_ADD,
|
||||
MATERIAL_BLEND_MODE_SUB,
|
||||
MATERIAL_BLEND_MODE_MUL
|
||||
MATERIAL_BLEND_MODE_MUL,
|
||||
MATERIAL_BLEND_MODE_PREMULT_ALPHA
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ static const char *flag_names[]={
|
|||
"No MipMaps",
|
||||
"Repeat",
|
||||
"Filter (Magnifying)",
|
||||
"Premultiply Alpha",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -55,6 +56,7 @@ static const char *flag_short_names[]={
|
|||
"NoMipMap",
|
||||
"Repeat",
|
||||
"Filter",
|
||||
"PMAlpha",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -919,6 +921,11 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref<Resourc
|
|||
image.fix_alpha_edges();
|
||||
}
|
||||
|
||||
if (image.get_format()==Image::FORMAT_RGBA && flags&IMAGE_FLAG_PREMULT_ALPHA) {
|
||||
|
||||
image.premultiply_alpha();
|
||||
}
|
||||
|
||||
|
||||
if (shrink>1) {
|
||||
|
||||
|
@ -972,6 +979,11 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref<Resourc
|
|||
image.fix_alpha_edges();
|
||||
}
|
||||
|
||||
if (image.get_format()==Image::FORMAT_RGBA && flags&IMAGE_FLAG_PREMULT_ALPHA) {
|
||||
|
||||
image.premultiply_alpha();
|
||||
}
|
||||
|
||||
int orig_w=image.get_width();
|
||||
int orig_h=image.get_height();
|
||||
|
||||
|
|
|
@ -91,7 +91,8 @@ public:
|
|||
IMAGE_FLAG_COMPRESS_EXTRA=8, // used for pvrtc2
|
||||
IMAGE_FLAG_NO_MIPMAPS=16, //normal for 2D games
|
||||
IMAGE_FLAG_REPEAT=32, //usually disabled in 2D
|
||||
IMAGE_FLAG_FILTER=64 //almost always enabled
|
||||
IMAGE_FLAG_FILTER=64, //almost always enabled
|
||||
IMAGE_FLAG_PREMULT_ALPHA=128//almost always enabled
|
||||
};
|
||||
|
||||
virtual String get_name() const;
|
||||
|
|
|
@ -134,6 +134,8 @@ public:
|
|||
|
||||
|
||||
void _plot_light(const Vector3& p_plot_pos,const AABB& p_plot_aabb, Octant *p_octant, const AABB& p_aabb,const Color& p_light);
|
||||
void _plot_light_point(const Vector3& p_plot_pos, Octant *p_octant, const AABB& p_aabb,const Color& p_light);
|
||||
|
||||
void _throw_ray(const Vector3& p_from, const Vector3& p_to,const Color& p_light,float *p_att_curve,float p_att_curve_len,int p_bounces);
|
||||
|
||||
|
||||
|
@ -165,7 +167,7 @@ public:
|
|||
}
|
||||
|
||||
BakedLightBaker() {
|
||||
octree_depth=8;
|
||||
octree_depth=6;
|
||||
octree=NULL;
|
||||
bvh=NULL;
|
||||
leaf_list=NULL;
|
||||
|
@ -408,7 +410,7 @@ void BakedLightBaker::_make_bvh() {
|
|||
void BakedLightBaker::_octree_insert(const AABB& p_aabb,Octant *p_octant,Triangle* p_triangle, int p_depth) {
|
||||
|
||||
if (p_octant->leaf) {
|
||||
|
||||
#if 0
|
||||
if (p_aabb.has_point(p_triangle->vertices[0]) && p_aabb.has_point(p_triangle->vertices[1]) &&p_aabb.has_point(p_triangle->vertices[2])) {
|
||||
//face is completely enclosed, add area
|
||||
p_octant->surface_area+=Face3(p_triangle->vertices[0],p_triangle->vertices[1],p_triangle->vertices[2]).get_area();
|
||||
|
@ -433,12 +435,18 @@ void BakedLightBaker::_octree_insert(const AABB& p_aabb,Octant *p_octant,Triangl
|
|||
p.d=-p_aabb.pos[i];
|
||||
poly=Geometry::clip_polygon(poly,p);
|
||||
}
|
||||
//calculate area
|
||||
for(int i=2;i<poly.size();i++) {
|
||||
p_octant->surface_area+=Face3(poly[0],poly[i-1],poly[i]).get_area();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//calculate area
|
||||
float clipped_area=0;
|
||||
for(int i=2;i<poly.size();i++) {
|
||||
clipped_area+=Face3(poly[0],poly[i-1],poly[i]).get_area();
|
||||
}
|
||||
|
||||
print_line(itos(poly.size())+" Base: "+rtos(Face3(p_triangle->vertices[0],p_triangle->vertices[1],p_triangle->vertices[2]).get_area())+" clipped: "+rtos(clipped_area));
|
||||
p_octant->surface_area+=clipped_area;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
|
||||
|
||||
|
@ -500,7 +508,7 @@ void BakedLightBaker::_make_octree() {
|
|||
octree_aabb=base;
|
||||
|
||||
cell_size=base.size.x;
|
||||
for(int i=0;i<=octree_depth;i++)
|
||||
for(int i=0;i<octree_depth;i++)
|
||||
cell_size/=2.0;
|
||||
|
||||
octree = memnew( Octant );
|
||||
|
@ -526,7 +534,7 @@ void BakedLightBaker::_plot_light(const Vector3& p_plot_pos,const AABB& p_plot_a
|
|||
float d = p_plot_pos.distance_to(center);
|
||||
if (d>r)
|
||||
return; //oh crap! outside radius
|
||||
float intensity = 1.0 - (d/r)*(d/r); //not gauss but..
|
||||
float intensity = 1.0;// - (d/r)*(d/r); //not gauss but..
|
||||
p_octant->light_accum[0]+=p_light.r*intensity;
|
||||
p_octant->light_accum[1]+=p_light.g*intensity;
|
||||
p_octant->light_accum[2]+=p_light.b*intensity;
|
||||
|
@ -558,6 +566,42 @@ void BakedLightBaker::_plot_light(const Vector3& p_plot_pos,const AABB& p_plot_a
|
|||
}
|
||||
}
|
||||
|
||||
void BakedLightBaker::_plot_light_point(const Vector3& p_plot_pos, Octant *p_octant, const AABB& p_aabb,const Color& p_light) {
|
||||
|
||||
|
||||
if (p_octant->leaf) {
|
||||
|
||||
p_octant->light_accum[0]+=p_light.r;
|
||||
p_octant->light_accum[1]+=p_light.g;
|
||||
p_octant->light_accum[2]+=p_light.b;
|
||||
|
||||
} else {
|
||||
|
||||
for(int i=0;i<8;i++) {
|
||||
|
||||
if (!p_octant->children[i])
|
||||
continue;
|
||||
|
||||
AABB aabb=p_aabb;
|
||||
aabb.size*=0.5;
|
||||
if (i&1)
|
||||
aabb.pos.x+=aabb.size.x;
|
||||
if (i&2)
|
||||
aabb.pos.y+=aabb.size.y;
|
||||
if (i&4)
|
||||
aabb.pos.z+=aabb.size.z;
|
||||
|
||||
|
||||
if (!aabb.has_point(p_plot_pos))
|
||||
continue;
|
||||
|
||||
_plot_light_point(p_plot_pos,p_octant->children[i],aabb,p_light);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BakedLightBaker::_throw_ray(const Vector3& p_begin, const Vector3& p_end,const Color& p_light,float *p_att_curve,float p_att_curve_len,int p_bounces) {
|
||||
|
||||
|
@ -692,6 +736,7 @@ void BakedLightBaker::_throw_ray(const Vector3& p_begin, const Vector3& p_end,co
|
|||
aabb.size=Vector3(2,2,2)*cell_size*plot_size;
|
||||
|
||||
_plot_light(r_point,aabb,octree,octree_aabb,p_light);
|
||||
// _plot_light_point(r_point,octree,octree_aabb,p_light);
|
||||
|
||||
}
|
||||
|
||||
|
@ -772,9 +817,21 @@ void BakedLightBaker::bake(Node* p_node) {
|
|||
|
||||
|
||||
|
||||
void BakedLightEditor::_end_baking() {
|
||||
|
||||
if (!bake_thread)
|
||||
return;
|
||||
|
||||
bake_thread_exit=true;
|
||||
Thread::wait_to_finish(bake_thread);
|
||||
bake_thread=NULL;
|
||||
bake_thread_exit=false;
|
||||
}
|
||||
|
||||
void BakedLightEditor::_node_removed(Node *p_node) {
|
||||
|
||||
if(p_node==node) {
|
||||
_end_baking();
|
||||
node=NULL;
|
||||
p_node->remove_child(preview);
|
||||
preview->set_mesh(Ref<Mesh>());
|
||||
|
@ -784,6 +841,79 @@ void BakedLightEditor::_node_removed(Node *p_node) {
|
|||
}
|
||||
|
||||
|
||||
void BakedLightEditor::_bake_thread_func(void *arg) {
|
||||
|
||||
BakedLightEditor *ble = (BakedLightEditor*)arg;
|
||||
|
||||
while(!ble->bake_thread_exit) {
|
||||
|
||||
ble->baker->throw_rays(1000);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void BakedLightEditor::_notification(int p_option) {
|
||||
|
||||
|
||||
if (p_option==NOTIFICATION_PROCESS) {
|
||||
|
||||
if (bake_thread) {
|
||||
|
||||
update_timeout-=get_process_delta_time();
|
||||
if (update_timeout<0) {
|
||||
|
||||
|
||||
|
||||
float norm = baker->get_normalization();
|
||||
float max_lum=0;
|
||||
{
|
||||
DVector<Color>::Write cw=colors.write();
|
||||
BakedLightBaker::Octant *oct = baker->leaf_list;
|
||||
int vert_idx=0;
|
||||
|
||||
while(oct) {
|
||||
|
||||
Color color;
|
||||
|
||||
|
||||
color.r=oct->light_accum[0]/norm;
|
||||
color.g=oct->light_accum[1]/norm;
|
||||
color.b=oct->light_accum[2]/norm;
|
||||
float lum = color.get_v();
|
||||
//if (lum<0.05)
|
||||
// color.a=0;
|
||||
if (lum>max_lum)
|
||||
max_lum=lum;
|
||||
|
||||
for (int i=0;i<36;i++) {
|
||||
|
||||
|
||||
cw[vert_idx++]=color;
|
||||
}
|
||||
|
||||
oct=oct->next_leaf;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Array a;
|
||||
a.resize(Mesh::ARRAY_MAX);
|
||||
a[Mesh::ARRAY_VERTEX]=vertices;
|
||||
a[Mesh::ARRAY_COLOR]=colors;
|
||||
while(mesh->get_surface_count())
|
||||
mesh->surface_remove(0);
|
||||
mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES,a);
|
||||
mesh->surface_set_material(0,material);
|
||||
|
||||
update_timeout=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BakedLightEditor::_menu_option(int p_option) {
|
||||
|
||||
|
@ -797,13 +927,9 @@ void BakedLightEditor::_menu_option(int p_option) {
|
|||
preview->set_mesh(Ref<Mesh>());
|
||||
baker->base_inv=node->get_global_transform().affine_inverse();
|
||||
baker->bake(node);
|
||||
baker->throw_rays(100000);
|
||||
float norm = baker->get_normalization();
|
||||
float max_lum=0;
|
||||
|
||||
print_line("CELLS: "+itos(baker->cell_count));
|
||||
DVector<Color> colors;
|
||||
DVector<Vector3> vertices;
|
||||
print_line("cell size: "+rtos(baker->cell_size));
|
||||
colors.resize(baker->cell_count*36);
|
||||
vertices.resize(baker->cell_count*36);
|
||||
|
||||
|
@ -817,12 +943,6 @@ void BakedLightEditor::_menu_option(int p_option) {
|
|||
while(oct) {
|
||||
|
||||
Color color;
|
||||
color.r=oct->light_accum[0]/norm;
|
||||
color.g=oct->light_accum[1]/norm;
|
||||
color.b=oct->light_accum[2]/norm;
|
||||
float lum = color.get_v();
|
||||
if (lum>max_lum)
|
||||
max_lum=lum;
|
||||
|
||||
for (int i=0;i<6;i++) {
|
||||
|
||||
|
@ -845,7 +965,7 @@ void BakedLightEditor::_menu_option(int p_option) {
|
|||
}
|
||||
|
||||
for(int j=0;j<4;j++) {
|
||||
face_points[j]*=baker->cell_size;
|
||||
face_points[j]*=baker->cell_size*0.5;
|
||||
face_points[j]+=Vector3(oct->offset[0],oct->offset[1],oct->offset[2]);
|
||||
}
|
||||
|
||||
|
@ -873,25 +993,20 @@ void BakedLightEditor::_menu_option(int p_option) {
|
|||
|
||||
}
|
||||
|
||||
print_line("max lum: "+rtos(max_lum));
|
||||
Array a;
|
||||
a.resize(Mesh::ARRAY_MAX);
|
||||
a[Mesh::ARRAY_VERTEX]=vertices;
|
||||
a[Mesh::ARRAY_COLOR]=colors;
|
||||
while(mesh->get_surface_count())
|
||||
mesh->surface_remove(0);
|
||||
mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES,a);
|
||||
mesh->surface_set_material(0,material);
|
||||
|
||||
Ref<FixedMaterial> matcol = memnew( FixedMaterial );
|
||||
matcol->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY,true);
|
||||
matcol->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true);
|
||||
matcol->set_flag(FixedMaterial::FLAG_UNSHADED,true);
|
||||
matcol->set_flag(FixedMaterial::FLAG_DOUBLE_SIDED,true);
|
||||
matcol->set_parameter(FixedMaterial::PARAM_DIFFUSE,Color(1,1,1));
|
||||
Ref<Mesh> m = memnew( Mesh );
|
||||
m->add_surface(Mesh::PRIMITIVE_TRIANGLES,a);
|
||||
m->surface_set_material(0,matcol);
|
||||
preview->set_mesh(m);
|
||||
|
||||
|
||||
|
||||
bake_thread_exit=false;
|
||||
update_timeout=0;
|
||||
set_process(true);
|
||||
bake_thread=Thread::create(_bake_thread_func,this);
|
||||
preview->set_mesh(mesh);
|
||||
|
||||
|
||||
} break;
|
||||
|
@ -914,6 +1029,7 @@ void BakedLightEditor::edit(BakedLight *p_baked_light) {
|
|||
}
|
||||
|
||||
node=p_baked_light;
|
||||
_end_baking();
|
||||
|
||||
if (node)
|
||||
node->add_child(preview);
|
||||
|
@ -943,6 +1059,19 @@ BakedLightEditor::BakedLightEditor() {
|
|||
node=NULL;
|
||||
baker = memnew( BakedLightBaker );
|
||||
preview = memnew( MeshInstance );
|
||||
bake_thread=NULL;
|
||||
update_timeout=0;
|
||||
|
||||
material = Ref<FixedMaterial> ( memnew( FixedMaterial ) );
|
||||
material->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY,true);
|
||||
material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true);
|
||||
material->set_flag(FixedMaterial::FLAG_UNSHADED,true);
|
||||
material->set_flag(FixedMaterial::FLAG_DOUBLE_SIDED,true);
|
||||
material->set_parameter(FixedMaterial::PARAM_DIFFUSE,Color(1,1,1));
|
||||
|
||||
mesh = Ref<Mesh>( memnew( Mesh ));
|
||||
|
||||
|
||||
}
|
||||
|
||||
BakedLightEditor::~BakedLightEditor() {
|
||||
|
|
|
@ -19,6 +19,15 @@ class BakedLightEditor : public Control {
|
|||
OBJ_TYPE(BakedLightEditor, Control );
|
||||
|
||||
|
||||
float update_timeout;
|
||||
DVector<Color> colors;
|
||||
DVector<Vector3> vertices;
|
||||
Ref<Mesh> mesh;
|
||||
Ref<FixedMaterial> material;
|
||||
|
||||
Thread *bake_thread;
|
||||
bool bake_thread_exit;
|
||||
|
||||
MeshInstance *preview;
|
||||
BakedLightBaker *baker;
|
||||
AcceptDialog *err_dialog;
|
||||
|
@ -32,12 +41,15 @@ class BakedLightEditor : public Control {
|
|||
MENU_OPTION_CLEAR
|
||||
};
|
||||
|
||||
static void _bake_thread_func(void *arg);
|
||||
void _end_baking();
|
||||
void _menu_option(int);
|
||||
|
||||
friend class BakedLightEditorPlugin;
|
||||
protected:
|
||||
void _node_removed(Node *p_node);
|
||||
static void _bind_methods();
|
||||
void _notification(int p_what);
|
||||
public:
|
||||
|
||||
void edit(BakedLight *p_baked_light);
|
||||
|
|
|
@ -608,7 +608,14 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
|
|||
|
||||
if (b.button_index==BUTTON_WHEEL_DOWN) {
|
||||
|
||||
float prev_zoom=zoom;
|
||||
zoom=zoom*0.95;
|
||||
{
|
||||
Point2 ofs(b.x,b.y);
|
||||
ofs = ofs/prev_zoom - ofs/zoom;
|
||||
h_scroll->set_val( h_scroll->get_val() + ofs.x );
|
||||
v_scroll->set_val( v_scroll->get_val() + ofs.y );
|
||||
}
|
||||
_update_scroll(0);
|
||||
viewport->update();
|
||||
return;
|
||||
|
@ -616,7 +623,15 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
|
|||
|
||||
if (b.button_index==BUTTON_WHEEL_UP) {
|
||||
|
||||
float prev_zoom=zoom;
|
||||
zoom=zoom*(1.0/0.95);
|
||||
{
|
||||
Point2 ofs(b.x,b.y);
|
||||
ofs = ofs/prev_zoom - ofs/zoom;
|
||||
h_scroll->set_val( h_scroll->get_val() + ofs.x );
|
||||
v_scroll->set_val( v_scroll->get_val() + ofs.y );
|
||||
}
|
||||
|
||||
_update_scroll(0);
|
||||
viewport->update();
|
||||
return;
|
||||
|
|
|
@ -687,6 +687,26 @@ void ScriptEditor::_menu_option(int p_option) {
|
|||
|
||||
current->get_text_edit()->query_code_comple();
|
||||
|
||||
} break;
|
||||
case EDIT_AUTO_INDENT: {
|
||||
|
||||
TextEdit *te = current->get_text_edit();
|
||||
String text = te->get_text();
|
||||
Ref<Script> scr = current->get_edited_script();
|
||||
if (scr.is_null())
|
||||
return;
|
||||
int begin,end;
|
||||
if (te->is_selection_active()) {
|
||||
begin=te->get_selection_from_line();
|
||||
end=te->get_selection_to_line();
|
||||
} else {
|
||||
begin=0;
|
||||
end=te->get_line_count()-1;
|
||||
}
|
||||
scr->get_language()->auto_indent_code(text,begin,end);
|
||||
te->set_text(text);
|
||||
|
||||
|
||||
} break;
|
||||
case SEARCH_FIND: {
|
||||
|
||||
|
@ -1321,6 +1341,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
|
|||
edit_menu->get_popup()->add_item("Select All",EDIT_SELECT_ALL,KEY_MASK_CMD|KEY_A);
|
||||
edit_menu->get_popup()->add_separator();
|
||||
edit_menu->get_popup()->add_item("Complete Symbol",EDIT_COMPLETE,KEY_MASK_CMD|KEY_SPACE);
|
||||
edit_menu->get_popup()->add_item("Auto Indent",EDIT_AUTO_INDENT,KEY_MASK_CMD|KEY_I);
|
||||
edit_menu->get_popup()->connect("item_pressed", this,"_menu_option");
|
||||
|
||||
|
||||
|
|
|
@ -122,6 +122,7 @@ class ScriptEditor : public VBoxContainer {
|
|||
EDIT_PASTE,
|
||||
EDIT_SELECT_ALL,
|
||||
EDIT_COMPLETE,
|
||||
EDIT_AUTO_INDENT,
|
||||
SEARCH_FIND,
|
||||
SEARCH_FIND_NEXT,
|
||||
SEARCH_REPLACE,
|
||||
|
|
|
@ -1566,6 +1566,7 @@ CustomPropertyEditor::CustomPropertyEditor() {
|
|||
add_child(checks20[i]);
|
||||
checks20[i]->hide();
|
||||
checks20[i]->connect("pressed",this,"_action_pressed",make_binds(i));
|
||||
checks20[i]->set_tooltip("Bit "+itos(i)+", val "+itos(1<<i)+".");
|
||||
}
|
||||
|
||||
text_edit = memnew( TextEdit );
|
||||
|
|
Loading…
Reference in New Issue