Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
c78a06536e
71 changed files with 69998 additions and 70271 deletions
|
@ -90,7 +90,7 @@ protected:
|
||||||
PhysicsServer * ps = PhysicsServer::get_singleton();
|
PhysicsServer * ps = PhysicsServer::get_singleton();
|
||||||
|
|
||||||
RID mesh_instance = vs->instance_create2(type_mesh_map[p_shape],scenario);
|
RID mesh_instance = vs->instance_create2(type_mesh_map[p_shape],scenario);
|
||||||
RID body = ps->body_create(p_body,!p_active_default);
|
RID body = ps->body_create(p_body,!p_active_default);
|
||||||
ps->body_set_space(body,space);
|
ps->body_set_space(body,space);
|
||||||
ps->body_set_param(body,PhysicsServer::BODY_PARAM_BOUNCE,0.5);
|
ps->body_set_param(body,PhysicsServer::BODY_PARAM_BOUNCE,0.5);
|
||||||
//todo set space
|
//todo set space
|
||||||
|
|
|
@ -270,6 +270,7 @@ protected:
|
||||||
RID body = ps->body_create();
|
RID body = ps->body_create();
|
||||||
ps->body_add_shape(body,body_shape_data[p_shape].shape);
|
ps->body_add_shape(body,body_shape_data[p_shape].shape);
|
||||||
ps->body_set_space(body,space);
|
ps->body_set_space(body,space);
|
||||||
|
ps->body_set_continuous_collision_detection_mode(body,Physics2DServer::CCD_MODE_CAST_SHAPE);
|
||||||
ps->body_set_state(body,Physics2DServer::BODY_STATE_TRANSFORM,p_xform);
|
ps->body_set_state(body,Physics2DServer::BODY_STATE_TRANSFORM,p_xform);
|
||||||
|
|
||||||
// print_line("add body with xform: "+p_xform);
|
// print_line("add body with xform: "+p_xform);
|
||||||
|
|
|
@ -240,6 +240,7 @@ bool Globals::_load_resource_pack(const String& p_pack) {
|
||||||
|
|
||||||
//if data.pck is found, all directory access will be from here
|
//if data.pck is found, all directory access will be from here
|
||||||
DirAccess::make_default<DirAccessPack>(DirAccess::ACCESS_RESOURCES);
|
DirAccess::make_default<DirAccessPack>(DirAccess::ACCESS_RESOURCES);
|
||||||
|
using_datapack=true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1327,6 +1328,10 @@ void Globals::set_disable_platform_override(bool p_disable) {
|
||||||
disable_platform_override=p_disable;
|
disable_platform_override=p_disable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Globals::is_using_datapack() const {
|
||||||
|
|
||||||
|
return using_datapack;
|
||||||
|
}
|
||||||
|
|
||||||
void Globals::_bind_methods() {
|
void Globals::_bind_methods() {
|
||||||
|
|
||||||
|
@ -1439,6 +1444,8 @@ Globals::Globals() {
|
||||||
custom_prop_info["render/mipmap_policy"]=PropertyInfo(Variant::INT,"render/mipmap_policy",PROPERTY_HINT_ENUM,"Allow,Allow For Po2,Disallow");
|
custom_prop_info["render/mipmap_policy"]=PropertyInfo(Variant::INT,"render/mipmap_policy",PROPERTY_HINT_ENUM,"Allow,Allow For Po2,Disallow");
|
||||||
custom_prop_info["render/thread_model"]=PropertyInfo(Variant::INT,"render/thread_model",PROPERTY_HINT_ENUM,"Single-Unsafe,Single-Safe,Multi-Threaded");
|
custom_prop_info["render/thread_model"]=PropertyInfo(Variant::INT,"render/thread_model",PROPERTY_HINT_ENUM,"Single-Unsafe,Single-Safe,Multi-Threaded");
|
||||||
set("display/emulate_touchscreen",false);
|
set("display/emulate_touchscreen",false);
|
||||||
|
|
||||||
|
using_datapack=false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,7 @@ protected:
|
||||||
String resource_path;
|
String resource_path;
|
||||||
HashMap<String,PropertyInfo> custom_prop_info;
|
HashMap<String,PropertyInfo> custom_prop_info;
|
||||||
bool disable_platform_override;
|
bool disable_platform_override;
|
||||||
|
bool using_datapack;
|
||||||
|
|
||||||
|
|
||||||
bool _set(const StringName& p_name, const Variant& p_value);
|
bool _set(const StringName& p_name, const Variant& p_value);
|
||||||
|
@ -127,6 +128,8 @@ public:
|
||||||
|
|
||||||
void register_global_defaults();
|
void register_global_defaults();
|
||||||
|
|
||||||
|
bool is_using_datapack() const;
|
||||||
|
|
||||||
Globals();
|
Globals();
|
||||||
~Globals();
|
~Globals();
|
||||||
|
|
||||||
|
|
|
@ -26,396 +26,396 @@
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
#include "file_access_compressed.h"
|
#include "file_access_compressed.h"
|
||||||
#include "print_string.h"
|
#include "print_string.h"
|
||||||
void FileAccessCompressed::configure(const String& p_magic, Compression::Mode p_mode, int p_block_size) {
|
void FileAccessCompressed::configure(const String& p_magic, Compression::Mode p_mode, int p_block_size) {
|
||||||
|
|
||||||
magic=p_magic.ascii().get_data();
|
magic=p_magic.ascii().get_data();
|
||||||
if (magic.length()>4)
|
if (magic.length()>4)
|
||||||
magic=magic.substr(0,4);
|
magic=magic.substr(0,4);
|
||||||
else {
|
else {
|
||||||
while(magic.length()<4)
|
while(magic.length()<4)
|
||||||
magic+=" ";
|
magic+=" ";
|
||||||
}
|
}
|
||||||
|
|
||||||
cmode=p_mode;
|
cmode=p_mode;
|
||||||
block_size=p_block_size;
|
block_size=p_block_size;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define WRITE_FIT(m_bytes) \
|
#define WRITE_FIT(m_bytes) \
|
||||||
{\
|
{\
|
||||||
if (write_pos+(m_bytes) > write_max) {\
|
if (write_pos+(m_bytes) > write_max) {\
|
||||||
write_max=write_pos+(m_bytes);\
|
write_max=write_pos+(m_bytes);\
|
||||||
}\
|
}\
|
||||||
if (write_max > write_buffer_size) {\
|
if (write_max > write_buffer_size) {\
|
||||||
write_buffer_size = nearest_power_of_2( write_max );\
|
write_buffer_size = nearest_power_of_2( write_max );\
|
||||||
buffer.resize(write_buffer_size);\
|
buffer.resize(write_buffer_size);\
|
||||||
write_ptr=buffer.ptr();\
|
write_ptr=buffer.ptr();\
|
||||||
}\
|
}\
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Error FileAccessCompressed::open_after_magic(FileAccess *p_base) {
|
Error FileAccessCompressed::open_after_magic(FileAccess *p_base) {
|
||||||
|
|
||||||
|
|
||||||
f=p_base;
|
f=p_base;
|
||||||
cmode=(Compression::Mode)f->get_32();
|
cmode=(Compression::Mode)f->get_32();
|
||||||
block_size=f->get_32();
|
block_size=f->get_32();
|
||||||
read_total=f->get_32();
|
read_total=f->get_32();
|
||||||
int bc = (read_total/block_size)+1;
|
int bc = (read_total/block_size)+1;
|
||||||
int acc_ofs=f->get_pos()+bc*4;
|
int acc_ofs=f->get_pos()+bc*4;
|
||||||
int max_bs=0;
|
int max_bs=0;
|
||||||
for(int i=0;i<bc;i++) {
|
for(int i=0;i<bc;i++) {
|
||||||
|
|
||||||
ReadBlock rb;
|
ReadBlock rb;
|
||||||
rb.offset=acc_ofs;
|
rb.offset=acc_ofs;
|
||||||
rb.csize=f->get_32();
|
rb.csize=f->get_32();
|
||||||
acc_ofs+=rb.csize;
|
acc_ofs+=rb.csize;
|
||||||
max_bs=MAX(max_bs,rb.csize);
|
max_bs=MAX(max_bs,rb.csize);
|
||||||
read_blocks.push_back(rb);
|
read_blocks.push_back(rb);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
comp_buffer.resize(max_bs);
|
comp_buffer.resize(max_bs);
|
||||||
buffer.resize(block_size);
|
buffer.resize(block_size);
|
||||||
read_ptr=buffer.ptr();
|
read_ptr=buffer.ptr();
|
||||||
f->get_buffer(comp_buffer.ptr(),read_blocks[0].csize);
|
f->get_buffer(comp_buffer.ptr(),read_blocks[0].csize);
|
||||||
at_end=false;
|
at_end=false;
|
||||||
read_eof=false;
|
read_eof=false;
|
||||||
read_block_count=bc;
|
read_block_count=bc;
|
||||||
read_block_size=read_blocks.size()==1?read_total:block_size;
|
read_block_size=read_blocks.size()==1?read_total:block_size;
|
||||||
|
|
||||||
Compression::decompress(buffer.ptr(),read_block_size,comp_buffer.ptr(),read_blocks[0].csize,cmode);
|
Compression::decompress(buffer.ptr(),read_block_size,comp_buffer.ptr(),read_blocks[0].csize,cmode);
|
||||||
read_block=0;
|
read_block=0;
|
||||||
read_pos=0;
|
read_pos=0;
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Error FileAccessCompressed::_open(const String& p_path, int p_mode_flags){
|
Error FileAccessCompressed::_open(const String& p_path, int p_mode_flags){
|
||||||
|
|
||||||
ERR_FAIL_COND_V(p_mode_flags==READ_WRITE,ERR_UNAVAILABLE);
|
ERR_FAIL_COND_V(p_mode_flags==READ_WRITE,ERR_UNAVAILABLE);
|
||||||
|
|
||||||
if (f)
|
if (f)
|
||||||
close();
|
close();
|
||||||
|
|
||||||
|
|
||||||
Error err;
|
Error err;
|
||||||
f = FileAccess::open(p_path,p_mode_flags,&err);
|
f = FileAccess::open(p_path,p_mode_flags,&err);
|
||||||
if (err!=OK) {
|
if (err!=OK) {
|
||||||
//not openable
|
//not openable
|
||||||
|
|
||||||
f=NULL;
|
f=NULL;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_mode_flags&WRITE) {
|
if (p_mode_flags&WRITE) {
|
||||||
|
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
writing=true;
|
writing=true;
|
||||||
write_pos=0;
|
write_pos=0;
|
||||||
write_buffer_size=256;
|
write_buffer_size=256;
|
||||||
buffer.resize(256);
|
buffer.resize(256);
|
||||||
write_max=0;
|
write_max=0;
|
||||||
write_ptr=buffer.ptr();
|
write_ptr=buffer.ptr();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//don't store anything else unless it's done saving!
|
//don't store anything else unless it's done saving!
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
char rmagic[5];
|
char rmagic[5];
|
||||||
f->get_buffer((uint8_t*)rmagic,4);
|
f->get_buffer((uint8_t*)rmagic,4);
|
||||||
rmagic[4]=0;
|
rmagic[4]=0;
|
||||||
if (magic!=rmagic) {
|
if (magic!=rmagic) {
|
||||||
memdelete(f);
|
memdelete(f);
|
||||||
f=NULL;
|
f=NULL;
|
||||||
return ERR_FILE_UNRECOGNIZED;
|
return ERR_FILE_UNRECOGNIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
open_after_magic(f);
|
open_after_magic(f);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
|
|
||||||
}
|
}
|
||||||
void FileAccessCompressed::close(){
|
void FileAccessCompressed::close(){
|
||||||
|
|
||||||
if (!f)
|
if (!f)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
if (writing) {
|
if (writing) {
|
||||||
//save block table and all compressed blocks
|
//save block table and all compressed blocks
|
||||||
|
|
||||||
CharString mgc = magic.utf8();
|
CharString mgc = magic.utf8();
|
||||||
f->store_buffer((const uint8_t*)mgc.get_data(),mgc.length()); //write header 4
|
f->store_buffer((const uint8_t*)mgc.get_data(),mgc.length()); //write header 4
|
||||||
f->store_32(cmode); //write compression mode 4
|
f->store_32(cmode); //write compression mode 4
|
||||||
f->store_32(block_size); //write block size 4
|
f->store_32(block_size); //write block size 4
|
||||||
f->store_32(write_max); //max amount of data written 4
|
f->store_32(write_max); //max amount of data written 4
|
||||||
int bc=(write_max/block_size)+1;
|
int bc=(write_max/block_size)+1;
|
||||||
|
|
||||||
for(int i=0;i<bc;i++) {
|
for(int i=0;i<bc;i++) {
|
||||||
f->store_32(0); //compressed sizes, will update later
|
f->store_32(0); //compressed sizes, will update later
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Vector<int> block_sizes;
|
Vector<int> block_sizes;
|
||||||
for(int i=0;i<bc;i++) {
|
for(int i=0;i<bc;i++) {
|
||||||
|
|
||||||
int bl = i==(bc-1) ? write_max % block_size : block_size;
|
int bl = i==(bc-1) ? write_max % block_size : block_size;
|
||||||
uint8_t *bp = &write_ptr[i*block_size];
|
uint8_t *bp = &write_ptr[i*block_size];
|
||||||
|
|
||||||
Vector<uint8_t> cblock;
|
Vector<uint8_t> cblock;
|
||||||
cblock.resize(Compression::get_max_compressed_buffer_size(bl,cmode));
|
cblock.resize(Compression::get_max_compressed_buffer_size(bl,cmode));
|
||||||
int s = Compression::compress(cblock.ptr(),bp,bl,cmode);
|
int s = Compression::compress(cblock.ptr(),bp,bl,cmode);
|
||||||
|
|
||||||
f->store_buffer(cblock.ptr(),s);
|
f->store_buffer(cblock.ptr(),s);
|
||||||
block_sizes.push_back(s);
|
block_sizes.push_back(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
f->seek(16); //ok write block sizes
|
f->seek(16); //ok write block sizes
|
||||||
for(int i=0;i<bc;i++)
|
for(int i=0;i<bc;i++)
|
||||||
f->store_32(block_sizes[i]);
|
f->store_32(block_sizes[i]);
|
||||||
f->seek_end();
|
f->seek_end();
|
||||||
f->store_buffer((const uint8_t*)mgc.get_data(),mgc.length()); //magic at the end too
|
f->store_buffer((const uint8_t*)mgc.get_data(),mgc.length()); //magic at the end too
|
||||||
|
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|
||||||
comp_buffer.clear();
|
comp_buffer.clear();
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
read_blocks.clear();
|
read_blocks.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
memdelete(f);
|
memdelete(f);
|
||||||
f=NULL;
|
f=NULL;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileAccessCompressed::is_open() const{
|
bool FileAccessCompressed::is_open() const{
|
||||||
|
|
||||||
return f!=NULL;
|
return f!=NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileAccessCompressed::seek(size_t p_position){
|
void FileAccessCompressed::seek(size_t p_position){
|
||||||
|
|
||||||
ERR_FAIL_COND(!f);
|
ERR_FAIL_COND(!f);
|
||||||
if (writing) {
|
if (writing) {
|
||||||
|
|
||||||
ERR_FAIL_COND(p_position>write_max);
|
ERR_FAIL_COND(p_position>write_max);
|
||||||
|
|
||||||
write_pos=p_position;
|
write_pos=p_position;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
ERR_FAIL_COND(p_position>read_total);
|
ERR_FAIL_COND(p_position>read_total);
|
||||||
if (p_position==read_total) {
|
if (p_position==read_total) {
|
||||||
at_end=true;
|
at_end=true;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
int block_idx = p_position/block_size;
|
int block_idx = p_position/block_size;
|
||||||
if (block_idx!=read_block) {
|
if (block_idx!=read_block) {
|
||||||
|
|
||||||
read_block=block_idx;
|
read_block=block_idx;
|
||||||
f->seek(read_blocks[read_block].offset);
|
f->seek(read_blocks[read_block].offset);
|
||||||
f->get_buffer(comp_buffer.ptr(),read_blocks[read_block].csize);
|
f->get_buffer(comp_buffer.ptr(),read_blocks[read_block].csize);
|
||||||
Compression::decompress(buffer.ptr(),read_blocks.size()==1?read_total:block_size,comp_buffer.ptr(),read_blocks[read_block].csize,cmode);
|
Compression::decompress(buffer.ptr(),read_blocks.size()==1?read_total:block_size,comp_buffer.ptr(),read_blocks[read_block].csize,cmode);
|
||||||
read_block_size=read_block==read_block_count-1?read_total%block_size:block_size;
|
read_block_size=read_block==read_block_count-1?read_total%block_size:block_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
read_pos=p_position%block_size;
|
read_pos=p_position%block_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FileAccessCompressed::seek_end(int64_t p_position){
|
void FileAccessCompressed::seek_end(int64_t p_position){
|
||||||
|
|
||||||
ERR_FAIL_COND(!f);
|
ERR_FAIL_COND(!f);
|
||||||
if (writing) {
|
if (writing) {
|
||||||
|
|
||||||
seek(write_max+p_position);
|
seek(write_max+p_position);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
seek(read_total+p_position);
|
seek(read_total+p_position);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
size_t FileAccessCompressed::get_pos() const{
|
size_t FileAccessCompressed::get_pos() const{
|
||||||
|
|
||||||
ERR_FAIL_COND_V(!f,0);
|
ERR_FAIL_COND_V(!f,0);
|
||||||
if (writing) {
|
if (writing) {
|
||||||
|
|
||||||
return write_pos;
|
return write_pos;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
return read_block*block_size+read_pos;
|
return read_block*block_size+read_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
size_t FileAccessCompressed::get_len() const{
|
size_t FileAccessCompressed::get_len() const{
|
||||||
|
|
||||||
ERR_FAIL_COND_V(!f,0);
|
ERR_FAIL_COND_V(!f,0);
|
||||||
if (writing) {
|
if (writing) {
|
||||||
|
|
||||||
return write_max;
|
return write_max;
|
||||||
} else {
|
} else {
|
||||||
return read_total;
|
return read_total;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileAccessCompressed::eof_reached() const{
|
bool FileAccessCompressed::eof_reached() const{
|
||||||
|
|
||||||
ERR_FAIL_COND_V(!f,false);
|
ERR_FAIL_COND_V(!f,false);
|
||||||
if (writing) {
|
if (writing) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return read_eof;
|
return read_eof;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t FileAccessCompressed::get_8() const{
|
uint8_t FileAccessCompressed::get_8() const{
|
||||||
|
|
||||||
ERR_FAIL_COND_V(writing,0);
|
ERR_FAIL_COND_V(writing,0);
|
||||||
ERR_FAIL_COND_V(!f,0);
|
ERR_FAIL_COND_V(!f,0);
|
||||||
|
|
||||||
if (at_end) {
|
if (at_end) {
|
||||||
read_eof=true;
|
read_eof=true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ret = read_ptr[read_pos];
|
uint8_t ret = read_ptr[read_pos];
|
||||||
|
|
||||||
read_pos++;
|
read_pos++;
|
||||||
if (read_pos>=read_block_size) {
|
if (read_pos>=read_block_size) {
|
||||||
read_block++;
|
read_block++;
|
||||||
|
|
||||||
if (read_block<read_block_count) {
|
if (read_block<read_block_count) {
|
||||||
//read another block of compressed data
|
//read another block of compressed data
|
||||||
f->get_buffer(comp_buffer.ptr(),read_blocks[read_block].csize);
|
f->get_buffer(comp_buffer.ptr(),read_blocks[read_block].csize);
|
||||||
Compression::decompress(buffer.ptr(),read_blocks.size()==1?read_total:block_size,comp_buffer.ptr(),read_blocks[read_block].csize,cmode);
|
Compression::decompress(buffer.ptr(),read_blocks.size()==1?read_total:block_size,comp_buffer.ptr(),read_blocks[read_block].csize,cmode);
|
||||||
read_block_size=read_block==read_block_count-1?read_total%block_size:block_size;
|
read_block_size=read_block==read_block_count-1?read_total%block_size:block_size;
|
||||||
read_pos=0;
|
read_pos=0;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
read_block--;
|
read_block--;
|
||||||
at_end=true;
|
at_end=true;
|
||||||
ret =0;
|
ret =0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
int FileAccessCompressed::get_buffer(uint8_t *p_dst, int p_length) const{
|
int FileAccessCompressed::get_buffer(uint8_t *p_dst, int p_length) const{
|
||||||
|
|
||||||
ERR_FAIL_COND_V(writing,0);
|
ERR_FAIL_COND_V(writing,0);
|
||||||
ERR_FAIL_COND_V(!f,0);
|
ERR_FAIL_COND_V(!f,0);
|
||||||
|
|
||||||
if (at_end) {
|
if (at_end) {
|
||||||
read_eof=true;
|
read_eof=true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for(int i=0;i<p_length;i++) {
|
for(int i=0;i<p_length;i++) {
|
||||||
|
|
||||||
|
|
||||||
p_dst[i]=read_ptr[read_pos];
|
p_dst[i]=read_ptr[read_pos];
|
||||||
read_pos++;
|
read_pos++;
|
||||||
if (read_pos>=read_block_size) {
|
if (read_pos>=read_block_size) {
|
||||||
read_block++;
|
read_block++;
|
||||||
|
|
||||||
if (read_block<read_block_count) {
|
if (read_block<read_block_count) {
|
||||||
//read another block of compressed data
|
//read another block of compressed data
|
||||||
f->get_buffer(comp_buffer.ptr(),read_blocks[read_block].csize);
|
f->get_buffer(comp_buffer.ptr(),read_blocks[read_block].csize);
|
||||||
Compression::decompress(buffer.ptr(),read_blocks.size()==1?read_total:block_size,comp_buffer.ptr(),read_blocks[read_block].csize,cmode);
|
Compression::decompress(buffer.ptr(),read_blocks.size()==1?read_total:block_size,comp_buffer.ptr(),read_blocks[read_block].csize,cmode);
|
||||||
read_block_size=read_block==read_block_count-1?read_total%block_size:block_size;
|
read_block_size=read_block==read_block_count-1?read_total%block_size:block_size;
|
||||||
read_pos=0;
|
read_pos=0;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
read_block--;
|
read_block--;
|
||||||
at_end=true;
|
at_end=true;
|
||||||
if (i<p_length-1)
|
if (i<p_length-1)
|
||||||
read_eof=true;
|
read_eof=true;
|
||||||
return i;
|
return i;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return p_length;
|
return p_length;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Error FileAccessCompressed::get_error() const{
|
Error FileAccessCompressed::get_error() const{
|
||||||
|
|
||||||
return read_eof?ERR_FILE_EOF:OK;
|
return read_eof?ERR_FILE_EOF:OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileAccessCompressed::store_8(uint8_t p_dest){
|
void FileAccessCompressed::store_8(uint8_t p_dest){
|
||||||
|
|
||||||
ERR_FAIL_COND(!f);
|
ERR_FAIL_COND(!f);
|
||||||
ERR_FAIL_COND(!writing);
|
ERR_FAIL_COND(!writing);
|
||||||
|
|
||||||
WRITE_FIT(1);
|
WRITE_FIT(1);
|
||||||
write_ptr[write_pos++]=p_dest;
|
write_ptr[write_pos++]=p_dest;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileAccessCompressed::file_exists(const String& p_name){
|
bool FileAccessCompressed::file_exists(const String& p_name){
|
||||||
|
|
||||||
FileAccess *fa = FileAccess::open(p_name,FileAccess::READ);
|
FileAccess *fa = FileAccess::open(p_name,FileAccess::READ);
|
||||||
if (!fa)
|
if (!fa)
|
||||||
return false;
|
return false;
|
||||||
memdelete(fa);
|
memdelete(fa);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t FileAccessCompressed::_get_modified_time(const String& p_file) {
|
uint64_t FileAccessCompressed::_get_modified_time(const String& p_file) {
|
||||||
|
|
||||||
if (f)
|
if (f)
|
||||||
return f->get_modified_time(p_file);
|
return f->get_modified_time(p_file);
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileAccessCompressed::FileAccessCompressed() {
|
FileAccessCompressed::FileAccessCompressed() {
|
||||||
|
|
||||||
f=NULL;
|
f=NULL;
|
||||||
magic="GCMP";
|
magic="GCMP";
|
||||||
block_size=4096;
|
block_size=16384;
|
||||||
cmode=Compression::MODE_FASTLZ;
|
cmode=Compression::MODE_DEFLATE;
|
||||||
writing=false;
|
writing=false;
|
||||||
write_ptr=0;
|
write_ptr=0;
|
||||||
write_buffer_size=0;
|
write_buffer_size=0;
|
||||||
write_max=0;
|
write_max=0;
|
||||||
block_size=0;
|
block_size=0;
|
||||||
read_eof=false;
|
read_eof=false;
|
||||||
at_end=false;
|
at_end=false;
|
||||||
read_total=0;
|
read_total=0;
|
||||||
read_ptr=NULL;
|
read_ptr=NULL;
|
||||||
read_block=0;
|
read_block=0;
|
||||||
read_block_count=0;
|
read_block_count=0;
|
||||||
read_block_size=0;
|
read_block_size=0;
|
||||||
read_pos=0;
|
read_pos=0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FileAccessCompressed::~FileAccessCompressed(){
|
FileAccessCompressed::~FileAccessCompressed(){
|
||||||
|
|
||||||
if (f)
|
if (f)
|
||||||
close();
|
close();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,7 +115,7 @@ private:
|
||||||
Element* _nil;
|
Element* _nil;
|
||||||
int size_cache;
|
int size_cache;
|
||||||
|
|
||||||
_Data() {
|
_FORCE_INLINE_ _Data() {
|
||||||
#ifdef GLOBALNIL_DISABLED
|
#ifdef GLOBALNIL_DISABLED
|
||||||
_nil = memnew_allocator( Element, A );
|
_nil = memnew_allocator( Element, A );
|
||||||
_nil->parent=_nil->left=_nil->right=_nil;
|
_nil->parent=_nil->left=_nil->right=_nil;
|
||||||
|
|
|
@ -255,6 +255,16 @@ Vector2 Vector2::cubic_interpolate(const Vector2& p_b,const Vector2& p_pre_a, co
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector2 Vector2::slide(const Vector2& p_vec) const {
|
||||||
|
|
||||||
|
return p_vec - *this * this->dot(p_vec);
|
||||||
|
}
|
||||||
|
Vector2 Vector2::reflect(const Vector2& p_vec) const {
|
||||||
|
|
||||||
|
return p_vec - *this * this->dot(p_vec) * 2.0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Rect2::intersects_segment(const Point2& p_from, const Point2& p_to, Point2* r_pos,Point2* r_normal) const {
|
bool Rect2::intersects_segment(const Point2& p_from, const Point2& p_to, Point2* r_pos,Point2* r_normal) const {
|
||||||
|
|
||||||
|
|
|
@ -105,6 +105,8 @@ struct Vector2 {
|
||||||
Vector2 cubic_interpolate(const Vector2& p_b,const Vector2& p_pre_a, const Vector2& p_post_b,float p_t) const;
|
Vector2 cubic_interpolate(const Vector2& p_b,const Vector2& p_pre_a, const Vector2& p_post_b,float p_t) const;
|
||||||
Vector2 cubic_interpolate_soft(const Vector2& p_b,const Vector2& p_pre_a, const Vector2& p_post_b,float p_t) const;
|
Vector2 cubic_interpolate_soft(const Vector2& p_b,const Vector2& p_pre_a, const Vector2& p_post_b,float p_t) const;
|
||||||
|
|
||||||
|
Vector2 slide(const Vector2& p_vec) const;
|
||||||
|
Vector2 reflect(const Vector2& p_vec) const;
|
||||||
|
|
||||||
Vector2 operator+(const Vector2& p_v) const;
|
Vector2 operator+(const Vector2& p_v) const;
|
||||||
void operator+=(const Vector2& p_v);
|
void operator+=(const Vector2& p_v);
|
||||||
|
|
|
@ -298,6 +298,8 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
|
||||||
VCALL_LOCALMEM1R(Vector2,snapped);
|
VCALL_LOCALMEM1R(Vector2,snapped);
|
||||||
VCALL_LOCALMEM0R(Vector2,get_aspect);
|
VCALL_LOCALMEM0R(Vector2,get_aspect);
|
||||||
VCALL_LOCALMEM1R(Vector2,dot);
|
VCALL_LOCALMEM1R(Vector2,dot);
|
||||||
|
VCALL_LOCALMEM1R(Vector2,slide);
|
||||||
|
VCALL_LOCALMEM1R(Vector2,reflect);
|
||||||
// VCALL_LOCALMEM1R(Vector2,cross);
|
// VCALL_LOCALMEM1R(Vector2,cross);
|
||||||
|
|
||||||
VCALL_LOCALMEM0R(Rect2,get_area);
|
VCALL_LOCALMEM0R(Rect2,get_area);
|
||||||
|
@ -1192,6 +1194,8 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
|
||||||
ADDFUNC1(VECTOR2,VECTOR2,Vector2,snapped,VECTOR2,"by",varray());
|
ADDFUNC1(VECTOR2,VECTOR2,Vector2,snapped,VECTOR2,"by",varray());
|
||||||
ADDFUNC0(VECTOR2,REAL,Vector2,get_aspect,varray());
|
ADDFUNC0(VECTOR2,REAL,Vector2,get_aspect,varray());
|
||||||
ADDFUNC1(VECTOR2,REAL,Vector2,dot,VECTOR2,"with",varray());
|
ADDFUNC1(VECTOR2,REAL,Vector2,dot,VECTOR2,"with",varray());
|
||||||
|
ADDFUNC1(VECTOR2,REAL,Vector2,slide,VECTOR2,"vec",varray());
|
||||||
|
ADDFUNC1(VECTOR2,REAL,Vector2,reflect,VECTOR2,"vec",varray());
|
||||||
//ADDFUNC1(VECTOR2,REAL,Vector2,cross,VECTOR2,"with",varray());
|
//ADDFUNC1(VECTOR2,REAL,Vector2,cross,VECTOR2,"with",varray());
|
||||||
|
|
||||||
ADDFUNC0(RECT2,REAL,Rect2,get_area,varray());
|
ADDFUNC0(RECT2,REAL,Rect2,get_area,varray());
|
||||||
|
|
|
@ -15,6 +15,7 @@ func disable():
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
# Initalization here
|
# Initalization here
|
||||||
|
get_node("Timer").start()
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<resource_file type="PackedScene" subresource_count="5" version="0.99" version_name="Godot Engine v0.99.3037-pre-beta">
|
<resource_file type="PackedScene" subresource_count="5" version="1.0" version_name="Godot Engine v1.0.3917-beta1">
|
||||||
<ext_resource path="res://bullet.png" type="Texture"></ext_resource>
|
<ext_resource path="res://bullet.*" type="Texture"></ext_resource>
|
||||||
<ext_resource path="res://bullet.gd" type="GDScript"></ext_resource>
|
<ext_resource path="res://bullet.*" type="Script"></ext_resource>
|
||||||
<resource type="CircleShape2D" path="local://0">
|
<resource type="CircleShape2D" path="local://1">
|
||||||
<string name="resource/name"> "" </string>
|
|
||||||
<real name="custom_solver_bias"> 0 </real>
|
<real name="custom_solver_bias"> 0 </real>
|
||||||
<real name="radius"> 10 </real>
|
<real name="radius"> 10 </real>
|
||||||
<resource name="script/script"></resource>
|
|
||||||
</resource>
|
</resource>
|
||||||
<resource type="Animation" path="local://1">
|
<resource type="Animation" path="local://2">
|
||||||
<string name="resource/name"> "shutdown" </string>
|
<string name="resource/name"> "shutdown" </string>
|
||||||
<real name="length"> 1.5 </real>
|
<real name="length"> 1.5 </real>
|
||||||
<bool name="loop"> False </bool>
|
<bool name="loop"> False </bool>
|
||||||
|
@ -16,13 +15,13 @@
|
||||||
<string name="tracks/0/type"> "value" </string>
|
<string name="tracks/0/type"> "value" </string>
|
||||||
<node_path name="tracks/0/path"> "particles:config/emitting" </node_path>
|
<node_path name="tracks/0/path"> "particles:config/emitting" </node_path>
|
||||||
<int name="tracks/0/interp"> 1 </int>
|
<int name="tracks/0/interp"> 1 </int>
|
||||||
<dictionary name="tracks/0/keys">
|
<dictionary name="tracks/0/keys" shared="false">
|
||||||
<string> "cont" </string>
|
<string> "cont" </string>
|
||||||
<bool> False </bool>
|
<bool> False </bool>
|
||||||
<string> "transitions" </string>
|
<string> "transitions" </string>
|
||||||
<real_array len="1"> 1 </real_array>
|
<real_array len="1"> 1 </real_array>
|
||||||
<string> "values" </string>
|
<string> "values" </string>
|
||||||
<array len="1">
|
<array len="1" shared="false">
|
||||||
<bool> False </bool>
|
<bool> False </bool>
|
||||||
</array>
|
</array>
|
||||||
<string> "times" </string>
|
<string> "times" </string>
|
||||||
|
@ -31,13 +30,13 @@
|
||||||
<string name="tracks/1/type"> "value" </string>
|
<string name="tracks/1/type"> "value" </string>
|
||||||
<node_path name="tracks/1/path"> "sprite:visibility/self_opacity" </node_path>
|
<node_path name="tracks/1/path"> "sprite:visibility/self_opacity" </node_path>
|
||||||
<int name="tracks/1/interp"> 1 </int>
|
<int name="tracks/1/interp"> 1 </int>
|
||||||
<dictionary name="tracks/1/keys">
|
<dictionary name="tracks/1/keys" shared="false">
|
||||||
<string> "cont" </string>
|
<string> "cont" </string>
|
||||||
<bool> True </bool>
|
<bool> True </bool>
|
||||||
<string> "transitions" </string>
|
<string> "transitions" </string>
|
||||||
<real_array len="2"> 1, 1 </real_array>
|
<real_array len="2"> 1, 1 </real_array>
|
||||||
<string> "values" </string>
|
<string> "values" </string>
|
||||||
<array len="2">
|
<array len="2" shared="false">
|
||||||
<real> 1 </real>
|
<real> 1 </real>
|
||||||
<real> 0 </real>
|
<real> 0 </real>
|
||||||
</array>
|
</array>
|
||||||
|
@ -47,14 +46,14 @@
|
||||||
<string name="tracks/2/type"> "method" </string>
|
<string name="tracks/2/type"> "method" </string>
|
||||||
<node_path name="tracks/2/path"> "." </node_path>
|
<node_path name="tracks/2/path"> "." </node_path>
|
||||||
<int name="tracks/2/interp"> 1 </int>
|
<int name="tracks/2/interp"> 1 </int>
|
||||||
<dictionary name="tracks/2/keys">
|
<dictionary name="tracks/2/keys" shared="false">
|
||||||
<string> "transitions" </string>
|
<string> "transitions" </string>
|
||||||
<real_array len="1"> 1 </real_array>
|
<real_array len="1"> 1 </real_array>
|
||||||
<string> "values" </string>
|
<string> "values" </string>
|
||||||
<array len="1">
|
<array len="1" shared="false">
|
||||||
<dictionary>
|
<dictionary shared="false">
|
||||||
<string> "args" </string>
|
<string> "args" </string>
|
||||||
<array len="0">
|
<array len="0" shared="false">
|
||||||
</array>
|
</array>
|
||||||
<string> "method" </string>
|
<string> "method" </string>
|
||||||
<string> "queue_free" </string>
|
<string> "queue_free" </string>
|
||||||
|
@ -63,33 +62,25 @@
|
||||||
<string> "times" </string>
|
<string> "times" </string>
|
||||||
<real_array len="1"> 1.31 </real_array>
|
<real_array len="1"> 1.31 </real_array>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
<resource name="script/script"></resource>
|
|
||||||
</resource>
|
</resource>
|
||||||
<main_resource>
|
<main_resource>
|
||||||
<string name="resource/name"> "" </string>
|
<dictionary name="_bundled" shared="false">
|
||||||
<dictionary name="_bundled">
|
|
||||||
<string> "names" </string>
|
<string> "names" </string>
|
||||||
<string_array len="109">
|
<string_array len="111">
|
||||||
<string> "bullet" </string>
|
<string> "bullet" </string>
|
||||||
<string> "RigidBody2D" </string>
|
<string> "RigidBody2D" </string>
|
||||||
<string> "process/process" </string>
|
|
||||||
<string> "process/fixed_process" </string>
|
|
||||||
<string> "process/input" </string>
|
|
||||||
<string> "process/unhandled_input" </string>
|
|
||||||
<string> "process/mode" </string>
|
|
||||||
<string> "visibility/visible" </string>
|
<string> "visibility/visible" </string>
|
||||||
<string> "visibility/toplevel" </string>
|
|
||||||
<string> "visibility/opacity" </string>
|
<string> "visibility/opacity" </string>
|
||||||
<string> "visibility/self_opacity" </string>
|
<string> "visibility/self_opacity" </string>
|
||||||
<string> "visibility/on_top" </string>
|
<string> "visibility/on_top" </string>
|
||||||
<string> "visibility/blend_mode" </string>
|
|
||||||
<string> "transform/notify" </string>
|
|
||||||
<string> "transform/pos" </string>
|
<string> "transform/pos" </string>
|
||||||
<string> "transform/rot" </string>
|
<string> "transform/rot" </string>
|
||||||
<string> "transform/scale" </string>
|
<string> "transform/scale" </string>
|
||||||
<string> "shape_count" </string>
|
<string> "shape_count" </string>
|
||||||
<string> "shapes/0/shape" </string>
|
<string> "shapes/0/shape" </string>
|
||||||
<string> "shapes/0/transform" </string>
|
<string> "shapes/0/transform" </string>
|
||||||
|
<string> "shapes/0/trigger" </string>
|
||||||
<string> "mode" </string>
|
<string> "mode" </string>
|
||||||
<string> "mass" </string>
|
<string> "mass" </string>
|
||||||
<string> "friction" </string>
|
<string> "friction" </string>
|
||||||
|
@ -106,8 +97,10 @@
|
||||||
<string> "__meta__" </string>
|
<string> "__meta__" </string>
|
||||||
<string> "particles" </string>
|
<string> "particles" </string>
|
||||||
<string> "Particles2D" </string>
|
<string> "Particles2D" </string>
|
||||||
|
<string> "visibility/blend_mode" </string>
|
||||||
<string> "config/amount" </string>
|
<string> "config/amount" </string>
|
||||||
<string> "config/lifetime" </string>
|
<string> "config/lifetime" </string>
|
||||||
|
<string> "config/time_scale" </string>
|
||||||
<string> "config/preprocess" </string>
|
<string> "config/preprocess" </string>
|
||||||
<string> "config/emit_timeout" </string>
|
<string> "config/emit_timeout" </string>
|
||||||
<string> "config/emitting" </string>
|
<string> "config/emitting" </string>
|
||||||
|
@ -115,11 +108,14 @@
|
||||||
<string> "config/half_extents" </string>
|
<string> "config/half_extents" </string>
|
||||||
<string> "config/local_space" </string>
|
<string> "config/local_space" </string>
|
||||||
<string> "config/explosiveness" </string>
|
<string> "config/explosiveness" </string>
|
||||||
|
<string> "config/flip_h" </string>
|
||||||
|
<string> "config/flip_v" </string>
|
||||||
<string> "config/texture" </string>
|
<string> "config/texture" </string>
|
||||||
<string> "params/direction" </string>
|
<string> "params/direction" </string>
|
||||||
<string> "params/spread" </string>
|
<string> "params/spread" </string>
|
||||||
<string> "params/linear_velocity" </string>
|
<string> "params/linear_velocity" </string>
|
||||||
<string> "params/spin_velocity" </string>
|
<string> "params/spin_velocity" </string>
|
||||||
|
<string> "params/orbit_velocity" </string>
|
||||||
<string> "params/gravity_direction" </string>
|
<string> "params/gravity_direction" </string>
|
||||||
<string> "params/gravity_strength" </string>
|
<string> "params/gravity_strength" </string>
|
||||||
<string> "params/radial_accel" </string>
|
<string> "params/radial_accel" </string>
|
||||||
|
@ -132,6 +128,7 @@
|
||||||
<string> "randomness/spread" </string>
|
<string> "randomness/spread" </string>
|
||||||
<string> "randomness/linear_velocity" </string>
|
<string> "randomness/linear_velocity" </string>
|
||||||
<string> "randomness/spin_velocity" </string>
|
<string> "randomness/spin_velocity" </string>
|
||||||
|
<string> "randomness/orbit_velocity" </string>
|
||||||
<string> "randomness/gravity_direction" </string>
|
<string> "randomness/gravity_direction" </string>
|
||||||
<string> "randomness/gravity_strength" </string>
|
<string> "randomness/gravity_strength" </string>
|
||||||
<string> "randomness/radial_accel" </string>
|
<string> "randomness/radial_accel" </string>
|
||||||
|
@ -149,6 +146,7 @@
|
||||||
<string> "phase_2/color" </string>
|
<string> "phase_2/color" </string>
|
||||||
<string> "phase_3/pos" </string>
|
<string> "phase_3/pos" </string>
|
||||||
<string> "phase_3/color" </string>
|
<string> "phase_3/color" </string>
|
||||||
|
<string> "emission_points" </string>
|
||||||
<string> "sprite" </string>
|
<string> "sprite" </string>
|
||||||
<string> "Sprite" </string>
|
<string> "Sprite" </string>
|
||||||
<string> "texture" </string>
|
<string> "texture" </string>
|
||||||
|
@ -164,6 +162,7 @@
|
||||||
<string> "region_rect" </string>
|
<string> "region_rect" </string>
|
||||||
<string> "CollisionShape2D" </string>
|
<string> "CollisionShape2D" </string>
|
||||||
<string> "shape" </string>
|
<string> "shape" </string>
|
||||||
|
<string> "trigger" </string>
|
||||||
<string> "Timer" </string>
|
<string> "Timer" </string>
|
||||||
<string> "wait_time" </string>
|
<string> "wait_time" </string>
|
||||||
<string> "one_shot" </string>
|
<string> "one_shot" </string>
|
||||||
|
@ -173,8 +172,9 @@
|
||||||
<string> "playback/process_mode" </string>
|
<string> "playback/process_mode" </string>
|
||||||
<string> "playback/default_blend_time" </string>
|
<string> "playback/default_blend_time" </string>
|
||||||
<string> "root/root" </string>
|
<string> "root/root" </string>
|
||||||
<string> "speed" </string>
|
|
||||||
<string> "anims/shutdown" </string>
|
<string> "anims/shutdown" </string>
|
||||||
|
<string> "playback/active" </string>
|
||||||
|
<string> "playback/speed" </string>
|
||||||
<string> "blend_times" </string>
|
<string> "blend_times" </string>
|
||||||
<string> "autoplay" </string>
|
<string> "autoplay" </string>
|
||||||
<string> "disable" </string>
|
<string> "disable" </string>
|
||||||
|
@ -187,99 +187,150 @@
|
||||||
<string> "node_count" </string>
|
<string> "node_count" </string>
|
||||||
<int> 6 </int>
|
<int> 6 </int>
|
||||||
<string> "variants" </string>
|
<string> "variants" </string>
|
||||||
<array len="27">
|
<array len="27" shared="false">
|
||||||
<bool> False </bool>
|
|
||||||
<int> 0 </int>
|
|
||||||
<bool> True </bool>
|
<bool> True </bool>
|
||||||
<real> 1 </real>
|
<real> 1 </real>
|
||||||
<vector2> 0, 0 </vector2>
|
<vector2> 0, 0 </vector2>
|
||||||
<real> 0 </real>
|
<real> 0 </real>
|
||||||
<vector2> 1, 1 </vector2>
|
<vector2> 1, 1 </vector2>
|
||||||
<int> 1 </int>
|
<int> 1 </int>
|
||||||
<resource resource_type="CircleShape2D" path="local://0"> </resource>
|
<resource resource_type="Shape2D" path="local://1"> </resource>
|
||||||
<matrix32> 1, 0, 0, 1, 0, 0 </matrix32>
|
<matrix32> 1, 0, 0, 1, 0, 0 </matrix32>
|
||||||
<resource resource_type="GDScript" path="res://bullet.gd"> </resource>
|
<bool> False </bool>
|
||||||
<dictionary>
|
<int> 0 </int>
|
||||||
|
<int> 2 </int>
|
||||||
|
<resource resource_type="Script" path="res://bullet.*"> </resource>
|
||||||
|
<dictionary shared="false">
|
||||||
<string> "__editor_plugin_states__" </string>
|
<string> "__editor_plugin_states__" </string>
|
||||||
<dictionary>
|
<dictionary shared="false">
|
||||||
<string> "Script" </string>
|
<string> "Script" </string>
|
||||||
<dictionary>
|
<dictionary shared="false">
|
||||||
<string> "current" </string>
|
<string> "current" </string>
|
||||||
<int> 0 </int>
|
<int> 2 </int>
|
||||||
<string> "sources" </string>
|
<string> "sources" </string>
|
||||||
<array len="3">
|
<array len="3" shared="false">
|
||||||
<string> "res://enemy.gd" </string>
|
<string> "res://enemy.gd" </string>
|
||||||
<string> "res://player.gd" </string>
|
<string> "res://player.gd" </string>
|
||||||
<string> "res://bullet.gd" </string>
|
<string> "res://bullet.gd" </string>
|
||||||
</array>
|
</array>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
<string> "2D" </string>
|
<string> "2D" </string>
|
||||||
<dictionary>
|
<dictionary shared="false">
|
||||||
|
<string> "pixel_snap" </string>
|
||||||
|
<bool> False </bool>
|
||||||
<string> "zoom" </string>
|
<string> "zoom" </string>
|
||||||
<real> 3.424785 </real>
|
<real> 3.424785 </real>
|
||||||
<string> "ofs" </string>
|
<string> "ofs" </string>
|
||||||
<vector2> -74.7573, -35.9676 </vector2>
|
<vector2> -74.7573, -35.9676 </vector2>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
<string> "3D" </string>
|
<string> "3D" </string>
|
||||||
<dictionary>
|
<dictionary shared="false">
|
||||||
<string> "zfar" </string>
|
<string> "zfar" </string>
|
||||||
<real> 500 </real>
|
<real> 500 </real>
|
||||||
<string> "fov" </string>
|
<string> "fov" </string>
|
||||||
<real> 45 </real>
|
<real> 45 </real>
|
||||||
<string> "window_mode" </string>
|
<string> "viewports" </string>
|
||||||
<int> 0 </int>
|
<array len="4" shared="false">
|
||||||
<string> "window_0" </string>
|
<dictionary shared="false">
|
||||||
<dictionary>
|
<string> "distance" </string>
|
||||||
<string> "distance" </string>
|
<real> 4 </real>
|
||||||
<real> 10.07268 </real>
|
<string> "x_rot" </string>
|
||||||
<string> "default_light" </string>
|
<real> 0 </real>
|
||||||
<bool> True </bool>
|
<string> "y_rot" </string>
|
||||||
<string> "x_rot" </string>
|
<real> 0 </real>
|
||||||
<real> 0.337 </real>
|
<string> "use_orthogonal" </string>
|
||||||
<string> "y_rot" </string>
|
<bool> False </bool>
|
||||||
<real> -0.575 </real>
|
<string> "use_environment" </string>
|
||||||
<string> "show_grid" </string>
|
<bool> False </bool>
|
||||||
<bool> True </bool>
|
<string> "pos" </string>
|
||||||
<string> "show_origin" </string>
|
<vector3> 0, 0, 0 </vector3>
|
||||||
<bool> True </bool>
|
</dictionary>
|
||||||
<string> "pos" </string>
|
<dictionary shared="false">
|
||||||
<vector3> 0, 0, 0 </vector3>
|
<string> "distance" </string>
|
||||||
</dictionary>
|
<real> 4 </real>
|
||||||
|
<string> "x_rot" </string>
|
||||||
|
<real> 0 </real>
|
||||||
|
<string> "y_rot" </string>
|
||||||
|
<real> 0 </real>
|
||||||
|
<string> "use_orthogonal" </string>
|
||||||
|
<bool> False </bool>
|
||||||
|
<string> "use_environment" </string>
|
||||||
|
<bool> False </bool>
|
||||||
|
<string> "pos" </string>
|
||||||
|
<vector3> 0, 0, 0 </vector3>
|
||||||
|
</dictionary>
|
||||||
|
<dictionary shared="false">
|
||||||
|
<string> "distance" </string>
|
||||||
|
<real> 4 </real>
|
||||||
|
<string> "x_rot" </string>
|
||||||
|
<real> 0 </real>
|
||||||
|
<string> "y_rot" </string>
|
||||||
|
<real> 0 </real>
|
||||||
|
<string> "use_orthogonal" </string>
|
||||||
|
<bool> False </bool>
|
||||||
|
<string> "use_environment" </string>
|
||||||
|
<bool> False </bool>
|
||||||
|
<string> "pos" </string>
|
||||||
|
<vector3> 0, 0, 0 </vector3>
|
||||||
|
</dictionary>
|
||||||
|
<dictionary shared="false">
|
||||||
|
<string> "distance" </string>
|
||||||
|
<real> 4 </real>
|
||||||
|
<string> "x_rot" </string>
|
||||||
|
<real> 0 </real>
|
||||||
|
<string> "y_rot" </string>
|
||||||
|
<real> 0 </real>
|
||||||
|
<string> "use_orthogonal" </string>
|
||||||
|
<bool> False </bool>
|
||||||
|
<string> "use_environment" </string>
|
||||||
|
<bool> False </bool>
|
||||||
|
<string> "pos" </string>
|
||||||
|
<vector3> 0, 0, 0 </vector3>
|
||||||
|
</dictionary>
|
||||||
|
</array>
|
||||||
|
<string> "viewport_mode" </string>
|
||||||
|
<int> 1 </int>
|
||||||
|
<string> "default_light" </string>
|
||||||
|
<bool> True </bool>
|
||||||
|
<string> "show_grid" </string>
|
||||||
|
<bool> True </bool>
|
||||||
|
<string> "show_origin" </string>
|
||||||
|
<bool> True </bool>
|
||||||
<string> "znear" </string>
|
<string> "znear" </string>
|
||||||
<real> 0.1 </real>
|
<real> 0.1 </real>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
<string> "__editor_run_settings__" </string>
|
<string> "__editor_run_settings__" </string>
|
||||||
<dictionary>
|
<dictionary shared="false">
|
||||||
<string> "custom_args" </string>
|
<string> "custom_args" </string>
|
||||||
<string> "-l $scene" </string>
|
<string> "-l $scene" </string>
|
||||||
<string> "run_mode" </string>
|
<string> "run_mode" </string>
|
||||||
<int> 0 </int>
|
<int> 0 </int>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
<string> "__editor_plugin_screen__" </string>
|
<string> "__editor_plugin_screen__" </string>
|
||||||
<string> "Script" </string>
|
<string> "2D" </string>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
<real> 0.559322 </real>
|
<real> 0.559322 </real>
|
||||||
<int> 24 </int>
|
<int> 24 </int>
|
||||||
<real> 0.1 </real>
|
<real> 0.1 </real>
|
||||||
<resource resource_type="Texture" path="res://bullet.png"> </resource>
|
<resource resource_type="Texture" path="res://bullet.*"> </resource>
|
||||||
<real> 10 </real>
|
<real> 10 </real>
|
||||||
<int> 2 </int>
|
|
||||||
<color> 1, 1, 1, 1 </color>
|
<color> 1, 1, 1, 1 </color>
|
||||||
<color> 1, 0, 0, 0 </color>
|
<color> 1, 0, 0, 0 </color>
|
||||||
<color> 0, 0, 0, 1 </color>
|
<color> 0, 0, 0, 1 </color>
|
||||||
<resource name=""></resource> <rect2> 0, 0, 0, 0 </rect2>
|
<vector2_array len="0"> </vector2_array>
|
||||||
|
<rect2> 0, 0, 0, 0 </rect2>
|
||||||
<node_path> ".." </node_path>
|
<node_path> ".." </node_path>
|
||||||
<resource resource_type="Animation" path="local://1"> </resource>
|
<resource resource_type="Animation" path="local://2"> </resource>
|
||||||
<array len="0">
|
<array len="0" shared="false">
|
||||||
</array>
|
</array>
|
||||||
<string> "" </string>
|
<string> "" </string>
|
||||||
</array>
|
</array>
|
||||||
<string> "nodes" </string>
|
<string> "nodes" </string>
|
||||||
<int_array len="356"> -1, -1, 1, 0, -1, 32, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 0, 9, 3, 10, 3, 11, 2, 12, 1, 13, 2, 14, 4, 15, 5, 16, 6, 17, 7, 18, 8, 19, 9, 20, 1, 21, 3, 22, 3, 23, 5, 24, 0, 25, 0, 26, 1, 27, 0, 28, 2, 29, 2, 30, 4, 31, 5, 32, 10, 33, 11, 0, 0, 0, 35, 34, -1, 59, 2, 2, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 0, 9, 12, 10, 3, 11, 2, 12, 7, 13, 0, 14, 4, 15, 5, 16, 6, 36, 13, 37, 14, 38, 5, 39, 5, 40, 2, 41, 4, 42, 4, 43, 0, 44, 3, 45, 15, 46, 5, 47, 16, 48, 5, 49, 5, 50, 5, 51, 5, 52, 5, 53, 5, 54, 5, 55, 3, 56, 5, 57, 5, 58, 5, 59, 5, 60, 5, 61, 5, 62, 5, 63, 5, 64, 5, 65, 5, 66, 5, 67, 5, 68, 5, 69, 5, 70, 17, 71, 5, 72, 18, 73, 3, 74, 19, 75, 3, 76, 20, 77, 3, 78, 20, 32, 21, 0, 0, 0, 80, 79, -1, 27, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 0, 9, 3, 10, 3, 11, 2, 12, 1, 13, 0, 14, 4, 15, 5, 16, 6, 81, 15, 82, 2, 83, 4, 84, 0, 85, 0, 86, 7, 87, 7, 88, 1, 89, 18, 90, 0, 91, 22, 32, 21, 0, 0, 0, 92, 92, -1, 17, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 7, 2, 8, 0, 9, 3, 10, 3, 11, 2, 12, 1, 13, 2, 14, 4, 15, 5, 16, 6, 93, 8, 32, 21, 0, 0, 0, 94, 94, -1, 9, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 95, 3, 96, 2, 97, 2, 32, 21, 0, 0, 0, 99, 98, -1, 13, 2, 0, 3, 0, 4, 0, 5, 0, 6, 1, 100, 7, 101, 5, 102, 23, 103, 3, 104, 24, 105, 25, 106, 26, 32, 21, 0 </int_array>
|
<int_array len="282"> -1, -1, 1, 0, -1, 25, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 8, 13, 9, 14, 1, 15, 1, 16, 3, 17, 8, 18, 10, 19, 9, 20, 8, 21, 0, 22, 0, 23, 2, 24, 3, 25, 11, 26, 12, 0, 0, 0, 28, 27, -1, 57, 2, 0, 3, 13, 4, 1, 5, 0, 29, 5, 6, 2, 7, 3, 8, 4, 30, 14, 31, 15, 32, 1, 33, 3, 34, 3, 35, 0, 36, 2, 37, 2, 38, 8, 39, 1, 40, 8, 41, 8, 42, 16, 43, 3, 44, 17, 45, 3, 46, 3, 47, 3, 48, 3, 49, 3, 50, 3, 51, 3, 52, 3, 53, 1, 54, 3, 55, 3, 56, 3, 57, 3, 58, 3, 59, 3, 60, 3, 61, 3, 62, 3, 63, 3, 64, 3, 65, 3, 66, 3, 67, 3, 68, 3, 69, 10, 70, 3, 71, 18, 72, 1, 73, 19, 74, 1, 75, 20, 76, 1, 77, 20, 78, 21, 0, 0, 0, 80, 79, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 81, 16, 82, 0, 83, 2, 84, 8, 85, 8, 86, 5, 87, 5, 88, 9, 89, 18, 90, 8, 91, 22, 0, 0, 0, 92, 92, -1, 9, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 93, 6, 94, 8, 0, 0, 0, 95, 95, -1, 3, 96, 1, 97, 0, 98, 8, 0, 0, 0, 100, 99, -1, 8, 101, 5, 102, 3, 103, 23, 104, 24, 105, 0, 106, 1, 107, 25, 108, 26, 0 </int_array>
|
||||||
<string> "conns" </string>
|
<string> "conns" </string>
|
||||||
<int_array len="6"> 4, 0, 108, 107, 2, 0 </int_array>
|
<int_array len="6"> 4, 0, 110, 109, 2, 0 </int_array>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
<resource name="script/script"></resource>
|
|
||||||
</main_resource>
|
</main_resource>
|
||||||
</resource_file>
|
</resource_file>
|
|
@ -95,3 +95,4 @@ func _ready():
|
||||||
rc_right=get_node("raycast_right")
|
rc_right=get_node("raycast_right")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<main_resource>
|
<main_resource>
|
||||||
<dictionary name="_bundled" shared="false">
|
<dictionary name="_bundled" shared="false">
|
||||||
<string> "names" </string>
|
<string> "names" </string>
|
||||||
<string_array len="39">
|
<string_array len="46">
|
||||||
<string> "moving_platform" </string>
|
<string> "moving_platform" </string>
|
||||||
<string> "Node2D" </string>
|
<string> "Node2D" </string>
|
||||||
<string> "visibility/visible" </string>
|
<string> "visibility/visible" </string>
|
||||||
|
@ -25,16 +25,23 @@
|
||||||
<string> "motion" </string>
|
<string> "motion" </string>
|
||||||
<string> "cycle" </string>
|
<string> "cycle" </string>
|
||||||
<string> "platform" </string>
|
<string> "platform" </string>
|
||||||
<string> "StaticBody2D" </string>
|
<string> "RigidBody2D" </string>
|
||||||
<string> "shape_count" </string>
|
<string> "shape_count" </string>
|
||||||
<string> "shapes/0/shape" </string>
|
<string> "shapes/0/shape" </string>
|
||||||
<string> "shapes/0/transform" </string>
|
<string> "shapes/0/transform" </string>
|
||||||
<string> "shapes/0/trigger" </string>
|
<string> "shapes/0/trigger" </string>
|
||||||
<string> "simulate_motion" </string>
|
<string> "mode" </string>
|
||||||
<string> "constant_linear_velocity" </string>
|
<string> "mass" </string>
|
||||||
<string> "constant_angular_velocity" </string>
|
|
||||||
<string> "friction" </string>
|
<string> "friction" </string>
|
||||||
<string> "bounce" </string>
|
<string> "bounce" </string>
|
||||||
|
<string> "custom_integrator" </string>
|
||||||
|
<string> "continuous_cd" </string>
|
||||||
|
<string> "contacts_reported" </string>
|
||||||
|
<string> "contact_monitor" </string>
|
||||||
|
<string> "active" </string>
|
||||||
|
<string> "can_sleep" </string>
|
||||||
|
<string> "velocity/linear" </string>
|
||||||
|
<string> "velocity/angular" </string>
|
||||||
<string> "Sprite" </string>
|
<string> "Sprite" </string>
|
||||||
<string> "texture" </string>
|
<string> "texture" </string>
|
||||||
<string> "centered" </string>
|
<string> "centered" </string>
|
||||||
|
@ -58,7 +65,7 @@
|
||||||
<string> "node_count" </string>
|
<string> "node_count" </string>
|
||||||
<int> 4 </int>
|
<int> 4 </int>
|
||||||
<string> "variants" </string>
|
<string> "variants" </string>
|
||||||
<array len="16" shared="false">
|
<array len="17" shared="false">
|
||||||
<bool> True </bool>
|
<bool> True </bool>
|
||||||
<real> 1 </real>
|
<real> 1 </real>
|
||||||
<vector2> 0, 0 </vector2>
|
<vector2> 0, 0 </vector2>
|
||||||
|
@ -180,14 +187,15 @@
|
||||||
<resource resource_type="Shape2D" path="local://1"> </resource>
|
<resource resource_type="Shape2D" path="local://1"> </resource>
|
||||||
<matrix32> 1, -0, 0, 1, 0, 0 </matrix32>
|
<matrix32> 1, -0, 0, 1, 0, 0 </matrix32>
|
||||||
<bool> False </bool>
|
<bool> False </bool>
|
||||||
<resource resource_type="Texture" path="res://moving_platform.*"> </resource>
|
<int> 3 </int>
|
||||||
<int> 0 </int>
|
<int> 0 </int>
|
||||||
|
<resource resource_type="Texture" path="res://moving_platform.*"> </resource>
|
||||||
<color> 1, 1, 1, 1 </color>
|
<color> 1, 1, 1, 1 </color>
|
||||||
<rect2> 0, 0, 0, 0 </rect2>
|
<rect2> 0, 0, 0, 0 </rect2>
|
||||||
<vector2_array len="4"> -88, -24, 88, -24, 88, 24, -88, 24 </vector2_array>
|
<vector2_array len="4"> -88, -24, 88, -24, 88, 24, -88, 24 </vector2_array>
|
||||||
</array>
|
</array>
|
||||||
<string> "nodes" </string>
|
<string> "nodes" </string>
|
||||||
<int_array len="136"> -1, -1, 1, 0, -1, 11, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 2, 12, 1, 0, 0, 0, 14, 13, -1, 16, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 15, 7, 16, 8, 17, 9, 18, 10, 19, 0, 20, 2, 21, 3, 22, 1, 23, 3, 0, 1, 0, 24, 24, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 25, 11, 26, 0, 27, 2, 28, 10, 29, 10, 30, 7, 31, 7, 32, 12, 33, 13, 34, 10, 35, 14, 0, 1, 0, 36, 36, -1, 9, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 37, 12, 38, 15, 0 </int_array>
|
<int_array len="150"> -1, -1, 1, 0, -1, 11, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 2, 12, 1, 0, 0, 0, 14, 13, -1, 23, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 15, 7, 16, 8, 17, 9, 18, 10, 19, 11, 20, 1, 21, 1, 22, 3, 23, 10, 24, 10, 25, 12, 26, 10, 27, 0, 28, 0, 29, 2, 30, 3, 0, 1, 0, 31, 31, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 32, 13, 33, 0, 34, 2, 35, 10, 36, 10, 37, 7, 38, 7, 39, 12, 40, 14, 41, 10, 42, 15, 0, 1, 0, 43, 43, -1, 9, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 44, 12, 45, 16, 0 </int_array>
|
||||||
<string> "conns" </string>
|
<string> "conns" </string>
|
||||||
<int_array len="0"> </int_array>
|
<int_array len="0"> </int_array>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<resource_file type="PackedScene" subresource_count="24" version="1.0" version_name="Godot Engine v1.0.3917-beta1">
|
<resource_file type="PackedScene" subresource_count="24" version="1.0" version_name="Godot Engine v1.0.3917-beta1">
|
||||||
<ext_resource path="res://robot_demo.*" type="Texture"></ext_resource>
|
<ext_resource path="res://robot_demo.*" type="Texture"></ext_resource>
|
||||||
<ext_resource path="res://player.*" type="Script"></ext_resource>
|
|
||||||
<ext_resource path="res://sound_shoot.*" type="Sample"></ext_resource>
|
|
||||||
<ext_resource path="res://sound_coin.*" type="Sample"></ext_resource>
|
|
||||||
<ext_resource path="res://osb_right.*" type="Texture"></ext_resource>
|
|
||||||
<ext_resource path="res://sound_jump.*" type="Sample"></ext_resource>
|
|
||||||
<ext_resource path="res://osb_left.*" type="Texture"></ext_resource>
|
|
||||||
<ext_resource path="res://bullet.*" type="Texture"></ext_resource>
|
|
||||||
<ext_resource path="res://osb_jump.*" type="Texture"></ext_resource>
|
<ext_resource path="res://osb_jump.*" type="Texture"></ext_resource>
|
||||||
|
<ext_resource path="res://player.*" type="Script"></ext_resource>
|
||||||
|
<ext_resource path="res://osb_right.*" type="Texture"></ext_resource>
|
||||||
|
<ext_resource path="res://sound_coin.*" type="Sample"></ext_resource>
|
||||||
|
<ext_resource path="res://sound_jump.*" type="Sample"></ext_resource>
|
||||||
|
<ext_resource path="res://sound_shoot.*" type="Sample"></ext_resource>
|
||||||
|
<ext_resource path="res://bullet.*" type="Texture"></ext_resource>
|
||||||
<ext_resource path="res://osb_fire.*" type="Texture"></ext_resource>
|
<ext_resource path="res://osb_fire.*" type="Texture"></ext_resource>
|
||||||
|
<ext_resource path="res://osb_left.*" type="Texture"></ext_resource>
|
||||||
<resource type="RayShape2D" path="local://1">
|
<resource type="RayShape2D" path="local://1">
|
||||||
<real name="custom_solver_bias"> 0.5 </real>
|
<real name="custom_solver_bias"> 0.5 </real>
|
||||||
<real name="length"> 20 </real>
|
<real name="length"> 20 </real>
|
||||||
|
@ -101,50 +101,6 @@
|
||||||
|
|
||||||
</resource>
|
</resource>
|
||||||
<resource type="Animation" path="local://6">
|
<resource type="Animation" path="local://6">
|
||||||
<string name="resource/name"> "falling_weapon" </string>
|
|
||||||
<real name="length"> 0.5 </real>
|
|
||||||
<bool name="loop"> True </bool>
|
|
||||||
<real name="step"> 0.25 </real>
|
|
||||||
<string name="tracks/0/type"> "value" </string>
|
|
||||||
<node_path name="tracks/0/path"> "sprite:frame" </node_path>
|
|
||||||
<int name="tracks/0/interp"> 1 </int>
|
|
||||||
<dictionary name="tracks/0/keys" shared="false">
|
|
||||||
<string> "cont" </string>
|
|
||||||
<bool> False </bool>
|
|
||||||
<string> "transitions" </string>
|
|
||||||
<real_array len="1"> 1 </real_array>
|
|
||||||
<string> "values" </string>
|
|
||||||
<array len="1" shared="false">
|
|
||||||
<int> 26 </int>
|
|
||||||
</array>
|
|
||||||
<string> "times" </string>
|
|
||||||
<real_array len="1"> 0 </real_array>
|
|
||||||
</dictionary>
|
|
||||||
|
|
||||||
</resource>
|
|
||||||
<resource type="Animation" path="local://7">
|
|
||||||
<string name="resource/name"> "falling" </string>
|
|
||||||
<real name="length"> 0.01 </real>
|
|
||||||
<bool name="loop"> True </bool>
|
|
||||||
<real name="step"> 0.25 </real>
|
|
||||||
<string name="tracks/0/type"> "value" </string>
|
|
||||||
<node_path name="tracks/0/path"> "sprite:frame" </node_path>
|
|
||||||
<int name="tracks/0/interp"> 1 </int>
|
|
||||||
<dictionary name="tracks/0/keys" shared="false">
|
|
||||||
<string> "cont" </string>
|
|
||||||
<bool> False </bool>
|
|
||||||
<string> "transitions" </string>
|
|
||||||
<real_array len="1"> 1 </real_array>
|
|
||||||
<string> "values" </string>
|
|
||||||
<array len="1" shared="false">
|
|
||||||
<int> 21 </int>
|
|
||||||
</array>
|
|
||||||
<string> "times" </string>
|
|
||||||
<real_array len="1"> 0 </real_array>
|
|
||||||
</dictionary>
|
|
||||||
|
|
||||||
</resource>
|
|
||||||
<resource type="Animation" path="local://8">
|
|
||||||
<string name="resource/name"> "run_weapon" </string>
|
<string name="resource/name"> "run_weapon" </string>
|
||||||
<real name="length"> 1.25 </real>
|
<real name="length"> 1.25 </real>
|
||||||
<bool name="loop"> True </bool>
|
<bool name="loop"> True </bool>
|
||||||
|
@ -171,9 +127,9 @@
|
||||||
</dictionary>
|
</dictionary>
|
||||||
|
|
||||||
</resource>
|
</resource>
|
||||||
<resource type="Animation" path="local://9">
|
<resource type="Animation" path="local://7">
|
||||||
<string name="resource/name"> "run_gun_fire" </string>
|
<string name="resource/name"> "falling" </string>
|
||||||
<real name="length"> 1.25 </real>
|
<real name="length"> 0.01 </real>
|
||||||
<bool name="loop"> True </bool>
|
<bool name="loop"> True </bool>
|
||||||
<real name="step"> 0.25 </real>
|
<real name="step"> 0.25 </real>
|
||||||
<string name="tracks/0/type"> "value" </string>
|
<string name="tracks/0/type"> "value" </string>
|
||||||
|
@ -183,18 +139,57 @@
|
||||||
<string> "cont" </string>
|
<string> "cont" </string>
|
||||||
<bool> False </bool>
|
<bool> False </bool>
|
||||||
<string> "transitions" </string>
|
<string> "transitions" </string>
|
||||||
<real_array len="6"> 1, 1, 1, 1, 1, 1 </real_array>
|
<real_array len="1"> 1 </real_array>
|
||||||
<string> "values" </string>
|
<string> "values" </string>
|
||||||
<array len="6" shared="false">
|
<array len="1" shared="false">
|
||||||
<int> 10 </int>
|
<int> 21 </int>
|
||||||
<int> 11 </int>
|
|
||||||
<int> 12 </int>
|
|
||||||
<int> 13 </int>
|
|
||||||
<int> 14 </int>
|
|
||||||
<int> 5 </int>
|
|
||||||
</array>
|
</array>
|
||||||
<string> "times" </string>
|
<string> "times" </string>
|
||||||
<real_array len="6"> 0, 0.25, 0.5, 0.75, 1, 1.25 </real_array>
|
<real_array len="1"> 0 </real_array>
|
||||||
|
</dictionary>
|
||||||
|
|
||||||
|
</resource>
|
||||||
|
<resource type="Animation" path="local://8">
|
||||||
|
<string name="resource/name"> "falling_weapon" </string>
|
||||||
|
<real name="length"> 0.5 </real>
|
||||||
|
<bool name="loop"> True </bool>
|
||||||
|
<real name="step"> 0.25 </real>
|
||||||
|
<string name="tracks/0/type"> "value" </string>
|
||||||
|
<node_path name="tracks/0/path"> "sprite:frame" </node_path>
|
||||||
|
<int name="tracks/0/interp"> 1 </int>
|
||||||
|
<dictionary name="tracks/0/keys" shared="false">
|
||||||
|
<string> "cont" </string>
|
||||||
|
<bool> False </bool>
|
||||||
|
<string> "transitions" </string>
|
||||||
|
<real_array len="1"> 1 </real_array>
|
||||||
|
<string> "values" </string>
|
||||||
|
<array len="1" shared="false">
|
||||||
|
<int> 26 </int>
|
||||||
|
</array>
|
||||||
|
<string> "times" </string>
|
||||||
|
<real_array len="1"> 0 </real_array>
|
||||||
|
</dictionary>
|
||||||
|
|
||||||
|
</resource>
|
||||||
|
<resource type="Animation" path="local://9">
|
||||||
|
<string name="resource/name"> "idle_weapon" </string>
|
||||||
|
<real name="length"> 0.5 </real>
|
||||||
|
<bool name="loop"> True </bool>
|
||||||
|
<real name="step"> 0.25 </real>
|
||||||
|
<string name="tracks/0/type"> "value" </string>
|
||||||
|
<node_path name="tracks/0/path"> "sprite:frame" </node_path>
|
||||||
|
<int name="tracks/0/interp"> 1 </int>
|
||||||
|
<dictionary name="tracks/0/keys" shared="false">
|
||||||
|
<string> "cont" </string>
|
||||||
|
<bool> False </bool>
|
||||||
|
<string> "transitions" </string>
|
||||||
|
<real_array len="1"> 1 </real_array>
|
||||||
|
<string> "values" </string>
|
||||||
|
<array len="1" shared="false">
|
||||||
|
<int> 25 </int>
|
||||||
|
</array>
|
||||||
|
<string> "times" </string>
|
||||||
|
<real_array len="1"> 0 </real_array>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
|
|
||||||
</resource>
|
</resource>
|
||||||
|
@ -243,8 +238,8 @@
|
||||||
|
|
||||||
</resource>
|
</resource>
|
||||||
<resource type="Animation" path="local://12">
|
<resource type="Animation" path="local://12">
|
||||||
<string name="resource/name"> "idle_weapon" </string>
|
<string name="resource/name"> "run_gun_fire" </string>
|
||||||
<real name="length"> 0.5 </real>
|
<real name="length"> 1.25 </real>
|
||||||
<bool name="loop"> True </bool>
|
<bool name="loop"> True </bool>
|
||||||
<real name="step"> 0.25 </real>
|
<real name="step"> 0.25 </real>
|
||||||
<string name="tracks/0/type"> "value" </string>
|
<string name="tracks/0/type"> "value" </string>
|
||||||
|
@ -254,13 +249,18 @@
|
||||||
<string> "cont" </string>
|
<string> "cont" </string>
|
||||||
<bool> False </bool>
|
<bool> False </bool>
|
||||||
<string> "transitions" </string>
|
<string> "transitions" </string>
|
||||||
<real_array len="1"> 1 </real_array>
|
<real_array len="6"> 1, 1, 1, 1, 1, 1 </real_array>
|
||||||
<string> "values" </string>
|
<string> "values" </string>
|
||||||
<array len="1" shared="false">
|
<array len="6" shared="false">
|
||||||
<int> 25 </int>
|
<int> 10 </int>
|
||||||
|
<int> 11 </int>
|
||||||
|
<int> 12 </int>
|
||||||
|
<int> 13 </int>
|
||||||
|
<int> 14 </int>
|
||||||
|
<int> 5 </int>
|
||||||
</array>
|
</array>
|
||||||
<string> "times" </string>
|
<string> "times" </string>
|
||||||
<real_array len="1"> 0 </real_array>
|
<real_array len="6"> 0, 0.25, 0.5, 0.75, 1, 1.25 </real_array>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
|
|
||||||
</resource>
|
</resource>
|
||||||
|
@ -294,7 +294,7 @@
|
||||||
<main_resource>
|
<main_resource>
|
||||||
<dictionary name="_bundled" shared="false">
|
<dictionary name="_bundled" shared="false">
|
||||||
<string> "names" </string>
|
<string> "names" </string>
|
||||||
<string_array len="167">
|
<string_array len="170">
|
||||||
<string> "player" </string>
|
<string> "player" </string>
|
||||||
<string> "RigidBody2D" </string>
|
<string> "RigidBody2D" </string>
|
||||||
<string> "visibility/visible" </string>
|
<string> "visibility/visible" </string>
|
||||||
|
@ -351,6 +351,8 @@
|
||||||
<string> "config/half_extents" </string>
|
<string> "config/half_extents" </string>
|
||||||
<string> "config/local_space" </string>
|
<string> "config/local_space" </string>
|
||||||
<string> "config/explosiveness" </string>
|
<string> "config/explosiveness" </string>
|
||||||
|
<string> "config/flip_h" </string>
|
||||||
|
<string> "config/flip_v" </string>
|
||||||
<string> "config/texture" </string>
|
<string> "config/texture" </string>
|
||||||
<string> "params/direction" </string>
|
<string> "params/direction" </string>
|
||||||
<string> "params/spread" </string>
|
<string> "params/spread" </string>
|
||||||
|
@ -396,19 +398,20 @@
|
||||||
<string> "anims/idle" </string>
|
<string> "anims/idle" </string>
|
||||||
<string> "anims/jumping" </string>
|
<string> "anims/jumping" </string>
|
||||||
<string> "anims/run" </string>
|
<string> "anims/run" </string>
|
||||||
<string> "anims/falling_weapon" </string>
|
|
||||||
<string> "anims/falling" </string>
|
|
||||||
<string> "anims/run_weapon" </string>
|
<string> "anims/run_weapon" </string>
|
||||||
<string> "anims/standing_weapon_ready" </string>
|
<string> "anims/falling" </string>
|
||||||
|
<string> "anims/falling_weapon" </string>
|
||||||
|
<string> "anims/idle_weapon" </string>
|
||||||
<string> "anims/jumping_weapon" </string>
|
<string> "anims/jumping_weapon" </string>
|
||||||
<string> "anims/crouch" </string>
|
<string> "anims/crouch" </string>
|
||||||
<string> "anims/idle_weapon" </string>
|
<string> "anims/standing_weapon_ready" </string>
|
||||||
<string> "playback/active" </string>
|
<string> "playback/active" </string>
|
||||||
<string> "playback/speed" </string>
|
<string> "playback/speed" </string>
|
||||||
<string> "blend_times" </string>
|
<string> "blend_times" </string>
|
||||||
<string> "autoplay" </string>
|
<string> "autoplay" </string>
|
||||||
<string> "camera" </string>
|
<string> "camera" </string>
|
||||||
<string> "Camera2D" </string>
|
<string> "Camera2D" </string>
|
||||||
|
<string> "rotating" </string>
|
||||||
<string> "current" </string>
|
<string> "current" </string>
|
||||||
<string> "smoothing" </string>
|
<string> "smoothing" </string>
|
||||||
<string> "zoom" </string>
|
<string> "zoom" </string>
|
||||||
|
@ -651,7 +654,7 @@
|
||||||
<string> "shoot" </string>
|
<string> "shoot" </string>
|
||||||
</array>
|
</array>
|
||||||
<string> "nodes" </string>
|
<string> "nodes" </string>
|
||||||
<int_array len="566"> -1, -1, 1, 0, -1, 28, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 8, 13, 9, 14, 10, 15, 8, 16, 5, 17, 11, 18, 3, 19, 3, 20, 0, 21, 8, 22, 12, 23, 8, 24, 0, 25, 0, 26, 2, 27, 3, 28, 13, 29, 14, 0, 0, 0, 31, 30, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 32, 15, 33, 0, 34, 2, 35, 8, 36, 8, 37, 5, 38, 16, 39, 17, 40, 18, 41, 8, 42, 19, 0, 1, 0, 44, 43, -1, 55, 2, 0, 3, 1, 4, 20, 5, 0, 45, 17, 6, 21, 7, 22, 8, 4, 46, 23, 47, 24, 48, 1, 49, 3, 50, 24, 51, 8, 52, 2, 53, 2, 54, 8, 55, 25, 56, 26, 57, 3, 58, 27, 59, 28, 60, 1, 61, 3, 62, 3, 63, 29, 64, 3, 65, 3, 66, 3, 67, 30, 68, 30, 69, 3, 70, 3, 71, 3, 72, 3, 73, 30, 74, 3, 75, 3, 76, 3, 77, 3, 78, 3, 79, 3, 80, 3, 81, 3, 82, 3, 83, 5, 84, 3, 85, 18, 86, 1, 87, 31, 88, 1, 89, 32, 90, 1, 91, 33, 92, 34, 0, 0, 0, 94, 93, -1, 17, 95, 17, 96, 3, 97, 35, 98, 36, 99, 37, 100, 38, 101, 39, 102, 40, 103, 41, 104, 42, 105, 43, 106, 44, 107, 45, 108, 0, 109, 30, 110, 46, 111, 47, 0, 0, 0, 113, 112, -1, 21, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 33, 0, 114, 0, 115, 3, 116, 4, 117, 48, 118, 48, 119, 49, 120, 49, 121, 0, 122, 0, 123, 50, 124, 50, 125, 50, 126, 50, 0, 0, 0, 128, 127, -1, 7, 2, 0, 3, 1, 4, 1, 5, 0, 6, 51, 7, 3, 8, 4, 0, 0, 0, 129, 129, -1, 9, 2, 0, 3, 1, 4, 1, 5, 0, 6, 52, 7, 3, 8, 53, 130, 6, 131, 8, 0, 0, 0, 133, 132, -1, 14, 134, 12, 135, 54, 136, 3, 137, 1, 138, 3, 139, 3, 140, 3, 141, 55, 142, 55, 143, 55, 144, 55, 145, 5, 146, 3, 147, 3, 0, 0, 0, 148, 148, -1, 9, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 149, 48, 150, 56, 0, 0, 0, 152, 151, -1, 4, 153, 48, 34, 2, 154, 3, 155, 4, 0, 9, 0, 157, 156, -1, 13, 2, 0, 3, 1, 4, 1, 5, 0, 6, 57, 7, 3, 8, 58, 158, 59, 159, 60, 160, 60, 161, 0, 162, 61, 163, 17, 0, 9, 0, 157, 164, -1, 13, 2, 0, 3, 1, 4, 1, 5, 0, 6, 62, 7, 3, 8, 58, 158, 63, 159, 60, 160, 60, 161, 0, 162, 64, 163, 17, 0, 9, 0, 157, 165, -1, 13, 2, 0, 3, 1, 4, 1, 5, 0, 6, 65, 7, 3, 8, 58, 158, 66, 159, 60, 160, 60, 161, 8, 162, 67, 163, 17, 0, 9, 0, 157, 166, -1, 13, 2, 0, 3, 1, 4, 1, 5, 0, 6, 68, 7, 3, 8, 58, 158, 69, 159, 60, 160, 60, 161, 8, 162, 70, 163, 17, 0 </int_array>
|
<int_array len="572"> -1, -1, 1, 0, -1, 28, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 8, 13, 9, 14, 10, 15, 8, 16, 5, 17, 11, 18, 3, 19, 3, 20, 0, 21, 8, 22, 12, 23, 8, 24, 0, 25, 0, 26, 2, 27, 3, 28, 13, 29, 14, 0, 0, 0, 31, 30, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 32, 15, 33, 0, 34, 2, 35, 8, 36, 8, 37, 5, 38, 16, 39, 17, 40, 18, 41, 8, 42, 19, 0, 1, 0, 44, 43, -1, 57, 2, 0, 3, 1, 4, 20, 5, 0, 45, 17, 6, 21, 7, 22, 8, 4, 46, 23, 47, 24, 48, 1, 49, 3, 50, 24, 51, 8, 52, 2, 53, 2, 54, 8, 55, 25, 56, 8, 57, 8, 58, 26, 59, 3, 60, 27, 61, 28, 62, 1, 63, 3, 64, 3, 65, 29, 66, 3, 67, 3, 68, 3, 69, 30, 70, 30, 71, 3, 72, 3, 73, 3, 74, 3, 75, 30, 76, 3, 77, 3, 78, 3, 79, 3, 80, 3, 81, 3, 82, 3, 83, 3, 84, 3, 85, 5, 86, 3, 87, 18, 88, 1, 89, 31, 90, 1, 91, 32, 92, 1, 93, 33, 94, 34, 0, 0, 0, 96, 95, -1, 17, 97, 17, 98, 3, 99, 35, 100, 36, 101, 37, 102, 38, 103, 39, 104, 40, 105, 41, 106, 42, 107, 43, 108, 44, 109, 45, 110, 0, 111, 30, 112, 46, 113, 47, 0, 0, 0, 115, 114, -1, 22, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 33, 0, 116, 8, 117, 0, 118, 3, 119, 4, 120, 48, 121, 48, 122, 49, 123, 49, 124, 0, 125, 0, 126, 50, 127, 50, 128, 50, 129, 50, 0, 0, 0, 131, 130, -1, 7, 2, 0, 3, 1, 4, 1, 5, 0, 6, 51, 7, 3, 8, 4, 0, 0, 0, 132, 132, -1, 9, 2, 0, 3, 1, 4, 1, 5, 0, 6, 52, 7, 3, 8, 53, 133, 6, 134, 8, 0, 0, 0, 136, 135, -1, 14, 137, 12, 138, 54, 139, 3, 140, 1, 141, 3, 142, 3, 143, 3, 144, 55, 145, 55, 146, 55, 147, 55, 148, 5, 149, 3, 150, 3, 0, 0, 0, 151, 151, -1, 9, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 152, 48, 153, 56, 0, 0, 0, 155, 154, -1, 4, 156, 48, 34, 2, 157, 3, 158, 4, 0, 9, 0, 160, 159, -1, 13, 2, 0, 3, 1, 4, 1, 5, 0, 6, 57, 7, 3, 8, 58, 161, 59, 162, 60, 163, 60, 164, 0, 165, 61, 166, 17, 0, 9, 0, 160, 167, -1, 13, 2, 0, 3, 1, 4, 1, 5, 0, 6, 62, 7, 3, 8, 58, 161, 63, 162, 60, 163, 60, 164, 0, 165, 64, 166, 17, 0, 9, 0, 160, 168, -1, 13, 2, 0, 3, 1, 4, 1, 5, 0, 6, 65, 7, 3, 8, 58, 161, 66, 162, 60, 163, 60, 164, 8, 165, 67, 166, 17, 0, 9, 0, 160, 169, -1, 13, 2, 0, 3, 1, 4, 1, 5, 0, 6, 68, 7, 3, 8, 58, 161, 69, 162, 60, 163, 60, 164, 8, 165, 70, 166, 17, 0 </int_array>
|
||||||
<string> "conns" </string>
|
<string> "conns" </string>
|
||||||
<int_array len="0"> </int_array>
|
<int_array len="0"> </int_array>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<resource_file type="PackedScene" subresource_count="9" version="0.99" version_name="Godot Engine v0.99.3735-pre-beta">
|
<resource_file type="PackedScene" subresource_count="9" version="1.0" version_name="Godot Engine v1.0.3917-beta1">
|
||||||
<ext_resource path="res://music.*" type="AudioStreamOGGVorbis"></ext_resource>
|
<ext_resource path="res://music.*" type="AudioStream"></ext_resource>
|
||||||
<ext_resource path="res://tileset.*" type="TileSet"></ext_resource>
|
<ext_resource path="res://tileset.*" type="TileSet"></ext_resource>
|
||||||
<ext_resource path="res://seesaw.*" type="PackedScene"></ext_resource>
|
|
||||||
<ext_resource path="res://player.*" type="PackedScene"></ext_resource>
|
|
||||||
<ext_resource path="res://coin.*" type="PackedScene"></ext_resource>
|
<ext_resource path="res://coin.*" type="PackedScene"></ext_resource>
|
||||||
<ext_resource path="res://enemy.*" type="PackedScene"></ext_resource>
|
<ext_resource path="res://player.*" type="PackedScene"></ext_resource>
|
||||||
<ext_resource path="res://moving_platform.*" type="PackedScene"></ext_resource>
|
<ext_resource path="res://moving_platform.*" type="PackedScene"></ext_resource>
|
||||||
|
<ext_resource path="res://enemy.*" type="PackedScene"></ext_resource>
|
||||||
|
<ext_resource path="res://seesaw.*" type="PackedScene"></ext_resource>
|
||||||
<ext_resource path="res://parallax_bg.*" type="PackedScene"></ext_resource>
|
<ext_resource path="res://parallax_bg.*" type="PackedScene"></ext_resource>
|
||||||
<main_resource>
|
<main_resource>
|
||||||
<dictionary name="_bundled" shared="false">
|
<dictionary name="_bundled" shared="false">
|
||||||
<string> "names" </string>
|
<string> "names" </string>
|
||||||
<string_array len="92">
|
<string_array len="118">
|
||||||
<string> "stage" </string>
|
<string> "stage" </string>
|
||||||
<string> "Node" </string>
|
<string> "Node" </string>
|
||||||
<string> "__meta__" </string>
|
<string> "__meta__" </string>
|
||||||
|
@ -104,15 +104,41 @@
|
||||||
<string> "enemy 15" </string>
|
<string> "enemy 15" </string>
|
||||||
<string> "parallax_bg" </string>
|
<string> "parallax_bg" </string>
|
||||||
<string> "ParallaxBackground" </string>
|
<string> "ParallaxBackground" </string>
|
||||||
|
<string> "Label" </string>
|
||||||
|
<string> "margin/left" </string>
|
||||||
|
<string> "margin/top" </string>
|
||||||
|
<string> "margin/right" </string>
|
||||||
|
<string> "margin/bottom" </string>
|
||||||
|
<string> "focus_neighbour/left" </string>
|
||||||
|
<string> "focus_neighbour/top" </string>
|
||||||
|
<string> "focus_neighbour/right" </string>
|
||||||
|
<string> "focus_neighbour/bottom" </string>
|
||||||
|
<string> "focus/ignore_mouse" </string>
|
||||||
|
<string> "focus/stop_mouse" </string>
|
||||||
|
<string> "size_flags/horizontal" </string>
|
||||||
|
<string> "size_flags/stretch_ratio" </string>
|
||||||
|
<string> "range/min" </string>
|
||||||
|
<string> "range/max" </string>
|
||||||
|
<string> "range/step" </string>
|
||||||
|
<string> "range/page" </string>
|
||||||
|
<string> "range/value" </string>
|
||||||
|
<string> "range/exp_edit" </string>
|
||||||
|
<string> "rounded_values" </string>
|
||||||
|
<string> "text" </string>
|
||||||
|
<string> "align" </string>
|
||||||
|
<string> "valign" </string>
|
||||||
|
<string> "autowrap" </string>
|
||||||
|
<string> "uppercase" </string>
|
||||||
|
<string> "percent_visible" </string>
|
||||||
</string_array>
|
</string_array>
|
||||||
<string> "version" </string>
|
<string> "version" </string>
|
||||||
<int> 1 </int>
|
<int> 1 </int>
|
||||||
<string> "conn_count" </string>
|
<string> "conn_count" </string>
|
||||||
<int> 0 </int>
|
<int> 0 </int>
|
||||||
<string> "node_count" </string>
|
<string> "node_count" </string>
|
||||||
<int> 65 </int>
|
<int> 66 </int>
|
||||||
<string> "variants" </string>
|
<string> "variants" </string>
|
||||||
<array len="84" shared="false">
|
<array len="95" shared="false">
|
||||||
<dictionary shared="false">
|
<dictionary shared="false">
|
||||||
<string> "__editor_plugin_states__" </string>
|
<string> "__editor_plugin_states__" </string>
|
||||||
<dictionary shared="false">
|
<dictionary shared="false">
|
||||||
|
@ -133,9 +159,9 @@
|
||||||
<string> "pixel_snap" </string>
|
<string> "pixel_snap" </string>
|
||||||
<bool> False </bool>
|
<bool> False </bool>
|
||||||
<string> "zoom" </string>
|
<string> "zoom" </string>
|
||||||
<real> 0.598736 </real>
|
<real> 1.108033 </real>
|
||||||
<string> "ofs" </string>
|
<string> "ofs" </string>
|
||||||
<vector2> -37.7393, 205.061 </vector2>
|
<vector2> -19.8136, -223.194 </vector2>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
<string> "3D" </string>
|
<string> "3D" </string>
|
||||||
<dictionary shared="false">
|
<dictionary shared="false">
|
||||||
|
@ -297,7 +323,7 @@
|
||||||
<vector2> 450, 0 </vector2>
|
<vector2> 450, 0 </vector2>
|
||||||
<resource resource_type="PackedScene" path="res://seesaw.*"> </resource>
|
<resource resource_type="PackedScene" path="res://seesaw.*"> </resource>
|
||||||
<vector2> 2402.79, 849.52 </vector2>
|
<vector2> 2402.79, 849.52 </vector2>
|
||||||
<resource resource_type="AudioStreamOGGVorbis" path="res://music.*"> </resource>
|
<resource resource_type="AudioStream" path="res://music.*"> </resource>
|
||||||
<bool> False </bool>
|
<bool> False </bool>
|
||||||
<real> 2 </real>
|
<real> 2 </real>
|
||||||
<resource resource_type="PackedScene" path="res://enemy.*"> </resource>
|
<resource resource_type="PackedScene" path="res://enemy.*"> </resource>
|
||||||
|
@ -313,9 +339,20 @@
|
||||||
<vector2> 3546.2, 1356.19 </vector2>
|
<vector2> 3546.2, 1356.19 </vector2>
|
||||||
<vector2> 2406.63, 815.115 </vector2>
|
<vector2> 2406.63, 815.115 </vector2>
|
||||||
<resource resource_type="PackedScene" path="res://parallax_bg.*"> </resource>
|
<resource resource_type="PackedScene" path="res://parallax_bg.*"> </resource>
|
||||||
|
<real> 12 </real>
|
||||||
|
<real> -202 </real>
|
||||||
|
<real> 358 </real>
|
||||||
|
<real> -10 </real>
|
||||||
|
<node_path> "" </node_path>
|
||||||
|
<int> 2 </int>
|
||||||
|
<real> 14 </real>
|
||||||
|
<real> 14.769231 </real>
|
||||||
|
<string> "This is a simple demo on how to make a platformer game with Godot. This version uses physics and the 2D physics engine for motion and collision. The demo also shows the benefits of using the scene system, where coins, enemies and the player are edited separatedly and instanced in the stage. To edit the base tiles for the tileset, open the tileset_edit.xml file and follow instructions. " </string>
|
||||||
|
<int> 0 </int>
|
||||||
|
<real> -1 </real>
|
||||||
</array>
|
</array>
|
||||||
<string> "nodes" </string>
|
<string> "nodes" </string>
|
||||||
<int_array len="623"> -1, -1, 1, 0, -1, 1, 2, 0, 0, 0, 0, 4, 3, -1, 12, 5, 1, 6, 2, 7, 2, 8, 1, 9, 3, 10, 4, 11, 5, 12, 6, 13, 7, 14, 8, 15, 9, 2, 10, 0, 0, 0, 1, 16, -1, 1, 2, 11, 0, 2, 0, 18, 17, 12, 1, 9, 13, 0, 2, 0, 18, 19, 12, 1, 9, 14, 0, 2, 0, 18, 20, 12, 1, 9, 15, 0, 2, 0, 18, 21, 12, 1, 9, 16, 0, 2, 0, 18, 22, 12, 1, 9, 17, 0, 2, 0, 18, 23, 12, 1, 9, 18, 0, 2, 0, 18, 24, 12, 1, 9, 19, 0, 2, 0, 18, 25, 12, 1, 9, 20, 0, 2, 0, 18, 26, 12, 1, 9, 21, 0, 2, 0, 18, 27, 12, 1, 9, 22, 0, 2, 0, 18, 28, 12, 1, 9, 23, 0, 2, 0, 18, 29, 12, 1, 9, 24, 0, 2, 0, 18, 30, 12, 1, 9, 25, 0, 2, 0, 18, 31, 12, 1, 9, 26, 0, 2, 0, 18, 32, 12, 1, 9, 27, 0, 2, 0, 18, 33, 12, 1, 9, 28, 0, 2, 0, 18, 34, 12, 1, 9, 29, 0, 2, 0, 18, 35, 12, 1, 9, 30, 0, 2, 0, 18, 36, 12, 1, 9, 31, 0, 2, 0, 18, 37, 12, 1, 9, 32, 0, 2, 0, 18, 38, 12, 1, 9, 33, 0, 2, 0, 18, 39, 12, 1, 9, 34, 0, 2, 0, 18, 40, 12, 1, 9, 35, 0, 2, 0, 18, 41, 12, 1, 9, 36, 0, 2, 0, 18, 42, 12, 1, 9, 37, 0, 2, 0, 18, 43, 12, 1, 9, 38, 0, 2, 0, 18, 44, 12, 1, 9, 39, 0, 2, 0, 18, 45, 12, 1, 9, 40, 0, 2, 0, 18, 46, 12, 1, 9, 41, 0, 2, 0, 18, 47, 12, 1, 9, 42, 0, 2, 0, 18, 48, 12, 1, 9, 43, 0, 2, 0, 18, 49, 12, 1, 9, 44, 0, 2, 0, 18, 50, 12, 1, 9, 45, 0, 2, 0, 18, 51, 12, 1, 9, 46, 0, 2, 0, 18, 52, 12, 1, 9, 47, 0, 2, 0, 18, 53, 12, 1, 9, 48, 0, 2, 0, 18, 54, 12, 1, 9, 49, 0, 2, 0, 18, 55, 12, 1, 9, 50, 0, 2, 0, 18, 56, 12, 1, 9, 51, 0, 2, 0, 18, 57, 12, 1, 9, 52, 0, 2, 0, 18, 58, 12, 1, 9, 53, 0, 2, 0, 18, 59, 12, 1, 9, 54, 0, 0, 0, 61, 60, 55, 1, 9, 56, 0, 0, 0, 1, 62, -1, 0, 0, 46, 0, 64, 63, 57, 3, 9, 58, 65, 59, 66, 60, 0, 46, 0, 64, 67, 57, 3, 9, 61, 65, 62, 66, 63, 0, 46, 0, 64, 68, 57, 3, 9, 64, 65, 65, 66, 63, 0, 46, 0, 64, 69, 66, 1, 9, 67, 0, 0, 0, 71, 70, -1, 6, 72, 68, 73, 69, 74, 1, 75, 70, 76, 1, 77, 69, 0, 0, 0, 1, 78, -1, 0, 0, 52, 0, 61, 79, 71, 1, 9, 72, 0, 52, 0, 61, 80, 71, 1, 9, 73, 0, 52, 0, 61, 81, 71, 1, 9, 74, 0, 52, 0, 61, 82, 71, 1, 9, 75, 0, 52, 0, 61, 83, 71, 1, 9, 76, 0, 52, 0, 61, 84, 71, 1, 9, 77, 0, 52, 0, 61, 85, 71, 1, 9, 78, 0, 52, 0, 61, 86, 71, 1, 9, 79, 0, 52, 0, 61, 87, 71, 1, 9, 80, 0, 52, 0, 61, 88, 71, 1, 9, 81, 0, 52, 0, 61, 89, 71, 1, 9, 82, 0, 0, 0, 91, 90, 83, 0, 0 </int_array>
|
<int_array len="688"> -1, -1, 1, 0, -1, 1, 2, 0, 0, 0, 0, 4, 3, -1, 12, 5, 1, 6, 2, 7, 2, 8, 1, 9, 3, 10, 4, 11, 5, 12, 6, 13, 7, 14, 8, 15, 9, 2, 10, 0, 0, 0, 1, 16, -1, 1, 2, 11, 0, 2, 0, 18, 17, 12, 1, 9, 13, 0, 2, 0, 18, 19, 12, 1, 9, 14, 0, 2, 0, 18, 20, 12, 1, 9, 15, 0, 2, 0, 18, 21, 12, 1, 9, 16, 0, 2, 0, 18, 22, 12, 1, 9, 17, 0, 2, 0, 18, 23, 12, 1, 9, 18, 0, 2, 0, 18, 24, 12, 1, 9, 19, 0, 2, 0, 18, 25, 12, 1, 9, 20, 0, 2, 0, 18, 26, 12, 1, 9, 21, 0, 2, 0, 18, 27, 12, 1, 9, 22, 0, 2, 0, 18, 28, 12, 1, 9, 23, 0, 2, 0, 18, 29, 12, 1, 9, 24, 0, 2, 0, 18, 30, 12, 1, 9, 25, 0, 2, 0, 18, 31, 12, 1, 9, 26, 0, 2, 0, 18, 32, 12, 1, 9, 27, 0, 2, 0, 18, 33, 12, 1, 9, 28, 0, 2, 0, 18, 34, 12, 1, 9, 29, 0, 2, 0, 18, 35, 12, 1, 9, 30, 0, 2, 0, 18, 36, 12, 1, 9, 31, 0, 2, 0, 18, 37, 12, 1, 9, 32, 0, 2, 0, 18, 38, 12, 1, 9, 33, 0, 2, 0, 18, 39, 12, 1, 9, 34, 0, 2, 0, 18, 40, 12, 1, 9, 35, 0, 2, 0, 18, 41, 12, 1, 9, 36, 0, 2, 0, 18, 42, 12, 1, 9, 37, 0, 2, 0, 18, 43, 12, 1, 9, 38, 0, 2, 0, 18, 44, 12, 1, 9, 39, 0, 2, 0, 18, 45, 12, 1, 9, 40, 0, 2, 0, 18, 46, 12, 1, 9, 41, 0, 2, 0, 18, 47, 12, 1, 9, 42, 0, 2, 0, 18, 48, 12, 1, 9, 43, 0, 2, 0, 18, 49, 12, 1, 9, 44, 0, 2, 0, 18, 50, 12, 1, 9, 45, 0, 2, 0, 18, 51, 12, 1, 9, 46, 0, 2, 0, 18, 52, 12, 1, 9, 47, 0, 2, 0, 18, 53, 12, 1, 9, 48, 0, 2, 0, 18, 54, 12, 1, 9, 49, 0, 2, 0, 18, 55, 12, 1, 9, 50, 0, 2, 0, 18, 56, 12, 1, 9, 51, 0, 2, 0, 18, 57, 12, 1, 9, 52, 0, 2, 0, 18, 58, 12, 1, 9, 53, 0, 2, 0, 18, 59, 12, 1, 9, 54, 0, 0, 0, 61, 60, 55, 1, 9, 56, 0, 0, 0, 1, 62, -1, 0, 0, 46, 0, 64, 63, 57, 3, 9, 58, 65, 59, 66, 60, 0, 46, 0, 64, 67, 57, 3, 9, 61, 65, 62, 66, 63, 0, 46, 0, 64, 68, 57, 3, 9, 64, 65, 65, 66, 63, 0, 46, 0, 64, 69, 66, 1, 9, 67, 0, 0, 0, 71, 70, -1, 6, 72, 68, 73, 69, 74, 1, 75, 70, 76, 1, 77, 69, 0, 0, 0, 1, 78, -1, 0, 0, 52, 0, 61, 79, 71, 1, 9, 72, 0, 52, 0, 61, 80, 71, 1, 9, 73, 0, 52, 0, 61, 81, 71, 1, 9, 74, 0, 52, 0, 61, 82, 71, 1, 9, 75, 0, 52, 0, 61, 83, 71, 1, 9, 76, 0, 52, 0, 61, 84, 71, 1, 9, 77, 0, 52, 0, 61, 85, 71, 1, 9, 78, 0, 52, 0, 61, 86, 71, 1, 9, 79, 0, 52, 0, 61, 87, 71, 1, 9, 80, 0, 52, 0, 61, 88, 71, 1, 9, 81, 0, 52, 0, 61, 89, 71, 1, 9, 82, 0, 0, 0, 91, 90, 83, 0, 0, 0, 0, 92, 92, -1, 29, 5, 1, 6, 2, 7, 2, 8, 1, 93, 84, 94, 85, 95, 86, 96, 87, 97, 88, 98, 88, 99, 88, 100, 88, 101, 1, 102, 1, 103, 89, 104, 2, 105, 4, 106, 90, 107, 2, 108, 91, 109, 4, 110, 69, 111, 69, 112, 92, 113, 93, 114, 93, 115, 1, 116, 69, 117, 94, 0 </int_array>
|
||||||
<string> "conns" </string>
|
<string> "conns" </string>
|
||||||
<int_array len="0"> </int_array>
|
<int_array len="0"> </int_array>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -11027,6 +11027,9 @@
|
||||||
<return type="Vector2">
|
<return type="Vector2">
|
||||||
</return>
|
</return>
|
||||||
<description>
|
<description>
|
||||||
|
Return the global, unscaled, screen pointer coordinates.
|
||||||
|
If the 2D viewport has been scaled, it may not work well
|
||||||
|
with [Camera] or controls.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="get_mouse_speed" qualifiers="const" >
|
<method name="get_mouse_speed" qualifiers="const" >
|
||||||
|
@ -15411,6 +15414,7 @@
|
||||||
<brief_description>
|
<brief_description>
|
||||||
</brief_description>
|
</brief_description>
|
||||||
<description>
|
<description>
|
||||||
|
explain ownership, and that node does not need to own itself
|
||||||
</description>
|
</description>
|
||||||
<methods>
|
<methods>
|
||||||
<method name="pack" >
|
<method name="pack" >
|
||||||
|
@ -15419,6 +15423,8 @@
|
||||||
<argument index="0" name="path" type="Node">
|
<argument index="0" name="path" type="Node">
|
||||||
</argument>
|
</argument>
|
||||||
<description>
|
<description>
|
||||||
|
Pack will ignore any sub-nodes not owned by given
|
||||||
|
node. See [Node.set_owner].
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="instance" qualifiers="const" >
|
<method name="instance" qualifiers="const" >
|
||||||
|
@ -17490,7 +17496,7 @@
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="BODY_MODE_STATIC" value="0">
|
<constant name="BODY_MODE_STATIC" value="0">
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="BODY_MODE_STATIC_ACTIVE" value="1">
|
<constant name="BODY_MODE_KINEMATIC" value="1">
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="BODY_MODE_RIGID" value="2">
|
<constant name="BODY_MODE_RIGID" value="2">
|
||||||
</constant>
|
</constant>
|
||||||
|
@ -18420,7 +18426,7 @@
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="BODY_MODE_STATIC" value="0">
|
<constant name="BODY_MODE_STATIC" value="0">
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="BODY_MODE_STATIC_ACTIVE" value="1">
|
<constant name="BODY_MODE_KINEMATIC" value="1">
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="BODY_MODE_RIGID" value="2">
|
<constant name="BODY_MODE_RIGID" value="2">
|
||||||
</constant>
|
</constant>
|
||||||
|
@ -20861,7 +20867,7 @@
|
||||||
<constants>
|
<constants>
|
||||||
<constant name="MODE_STATIC" value="1">
|
<constant name="MODE_STATIC" value="1">
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="MODE_STATIC_ACTIVE" value="3">
|
<constant name="MODE_KINEMATIC" value="3">
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="MODE_RIGID" value="0">
|
<constant name="MODE_RIGID" value="0">
|
||||||
</constant>
|
</constant>
|
||||||
|
@ -21143,7 +21149,7 @@
|
||||||
<constant name="MODE_STATIC" value="1">
|
<constant name="MODE_STATIC" value="1">
|
||||||
Static mode (does not move, can't be moved).
|
Static mode (does not move, can't be moved).
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="MODE_STATIC_ACTIVE" value="3">
|
<constant name="MODE_KINEMATIC" value="3">
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="MODE_RIGID" value="0">
|
<constant name="MODE_RIGID" value="0">
|
||||||
Rigid body, can move and rotate.
|
Rigid body, can move and rotate.
|
||||||
|
|
|
@ -7511,7 +7511,7 @@ void RasterizerGLES2::init() {
|
||||||
pvr_supported=extensions.has("GL_IMG_texture_compression_pvrtc");
|
pvr_supported=extensions.has("GL_IMG_texture_compression_pvrtc");
|
||||||
etc_supported=extensions.has("GL_OES_compressed_ETC1_RGB8_texture");
|
etc_supported=extensions.has("GL_OES_compressed_ETC1_RGB8_texture");
|
||||||
use_depth24 = extensions.has("GL_OES_depth24");
|
use_depth24 = extensions.has("GL_OES_depth24");
|
||||||
s3tc_supported = extensions.has("GL_EXT_texture_compression_dxt1") || extensions.has("GL_EXT_texture_compression_s3tc");
|
s3tc_supported = extensions.has("GL_EXT_texture_compression_dxt1") || extensions.has("GL_EXT_texture_compression_s3tc") || extensions.has("WEBGL_compressed_texture_s3tc");
|
||||||
use_half_float = extensions.has("GL_OES_vertex_half_float");
|
use_half_float = extensions.has("GL_OES_vertex_half_float");
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -202,7 +202,7 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas
|
||||||
|
|
||||||
for(int i=0;i<argc;i++) {
|
for(int i=0;i<argc;i++) {
|
||||||
|
|
||||||
args.push_back(argv[i]);
|
args.push_back(String::utf8(argv[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String>::Element *I=args.front();
|
List<String>::Element *I=args.front();
|
||||||
|
@ -1037,18 +1037,24 @@ bool Main::start() {
|
||||||
|
|
||||||
if (!absolute) {
|
if (!absolute) {
|
||||||
|
|
||||||
int sep=local_game_path.find_last("/");
|
if (Globals::get_singleton()->is_using_datapack()) {
|
||||||
|
|
||||||
|
local_game_path="res://"+local_game_path;
|
||||||
|
|
||||||
if (sep==-1) {
|
|
||||||
DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
|
|
||||||
local_game_path=da->get_current_dir()+"/"+local_game_path;
|
|
||||||
memdelete(da) ;
|
|
||||||
} else {
|
} else {
|
||||||
|
int sep=local_game_path.find_last("/");
|
||||||
|
|
||||||
DirAccess *da = DirAccess::open(local_game_path.substr(0,sep));
|
if (sep==-1) {
|
||||||
if (da) {
|
DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
|
||||||
local_game_path=da->get_current_dir()+"/"+local_game_path.substr(sep+1,local_game_path.length());;
|
local_game_path=da->get_current_dir()+"/"+local_game_path;
|
||||||
memdelete(da);
|
memdelete(da) ;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
DirAccess *da = DirAccess::open(local_game_path.substr(0,sep));
|
||||||
|
if (da) {
|
||||||
|
local_game_path=da->get_current_dir()+"/"+local_game_path.substr(sep+1,local_game_path.length());;
|
||||||
|
memdelete(da);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -223,6 +223,7 @@ void OS_Android::process_touch(int p_what,int p_pointer, const Vector<TouchPos>&
|
||||||
ev.mouse_button.y=touch[0].pos.y;
|
ev.mouse_button.y=touch[0].pos.y;
|
||||||
ev.mouse_button.global_x=touch[0].pos.x;
|
ev.mouse_button.global_x=touch[0].pos.x;
|
||||||
ev.mouse_button.global_y=touch[0].pos.y;
|
ev.mouse_button.global_y=touch[0].pos.y;
|
||||||
|
input->set_mouse_pos(Point2(ev.mouse_button.x,ev.mouse_button.y));
|
||||||
main_loop->input_event(ev);
|
main_loop->input_event(ev);
|
||||||
|
|
||||||
|
|
||||||
|
@ -259,6 +260,7 @@ void OS_Android::process_touch(int p_what,int p_pointer, const Vector<TouchPos>&
|
||||||
ev.mouse_button.global_x=touch[0].pos.x;
|
ev.mouse_button.global_x=touch[0].pos.x;
|
||||||
ev.mouse_button.global_y=touch[0].pos.y;
|
ev.mouse_button.global_y=touch[0].pos.y;
|
||||||
last_mouse=touch[0].pos;
|
last_mouse=touch[0].pos;
|
||||||
|
input->set_mouse_pos(Point2(ev.mouse_button.x,ev.mouse_button.y));
|
||||||
main_loop->input_event(ev);
|
main_loop->input_event(ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -165,7 +165,7 @@ static int frame_count = 0;
|
||||||
printf("**************** app delegate init\n");
|
printf("**************** app delegate init\n");
|
||||||
CGRect rect = [[UIScreen mainScreen] bounds];
|
CGRect rect = [[UIScreen mainScreen] bounds];
|
||||||
|
|
||||||
[application setStatusBarHidden:YES animation:NO];
|
[application setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
|
||||||
// disable idle timer
|
// disable idle timer
|
||||||
application.idleTimerDisabled = YES;
|
application.idleTimerDisabled = YES;
|
||||||
|
|
||||||
|
|
|
@ -178,10 +178,11 @@ static void _fix_files(Vector<uint8_t>& html,uint64_t p_data_size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CharString cs = strnew.utf8();
|
CharString cs = strnew.utf8();
|
||||||
html.resize(cs.size());
|
html.resize(cs.length());
|
||||||
for(int i=9;i<cs.size();i++) {
|
for(int i=9;i<cs.length();i++) {
|
||||||
html[i]=cs[i];
|
html[i]=cs[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct JSExportData {
|
struct JSExportData {
|
||||||
|
|
|
@ -70,27 +70,7 @@ real_t StaticBody2D::get_constant_angular_velocity() const {
|
||||||
|
|
||||||
return constant_angular_velocity;
|
return constant_angular_velocity;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
|
||||||
void StaticBody2D::_state_notify(Object *p_object) {
|
|
||||||
|
|
||||||
if (!pre_xform)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Physics2DDirectBodyState *p2d = (Physics2DDirectBodyState*)p_object;
|
|
||||||
setting=true;
|
|
||||||
|
|
||||||
Matrix32 new_xform = p2d->get_transform();
|
|
||||||
*pre_xform=new_xform;
|
|
||||||
set_block_transform_notify(true);
|
|
||||||
set_global_transform(new_xform);
|
|
||||||
set_block_transform_notify(false);
|
|
||||||
|
|
||||||
setting=false;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void StaticBody2D::_update_xform() {
|
void StaticBody2D::_update_xform() {
|
||||||
|
|
||||||
if (!pre_xform || !pending)
|
if (!pre_xform || !pending)
|
||||||
|
@ -112,58 +92,7 @@ void StaticBody2D::_update_xform() {
|
||||||
pending=false;
|
pending=false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
void StaticBody2D::_notification(int p_what) {
|
|
||||||
|
|
||||||
switch(p_what) {
|
|
||||||
|
|
||||||
case NOTIFICATION_ENTER_SCENE: {
|
|
||||||
|
|
||||||
if (pre_xform)
|
|
||||||
*pre_xform = get_global_transform();
|
|
||||||
pending=false;
|
|
||||||
} break;
|
|
||||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
|
||||||
|
|
||||||
if (simulating_motion && !pending && is_inside_scene() && !setting && !get_scene()->is_editor_hint()) {
|
|
||||||
|
|
||||||
|
|
||||||
call_deferred(SceneStringNames::get_singleton()->_update_xform);
|
|
||||||
pending=true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void StaticBody2D::set_simulate_motion(bool p_enable) {
|
|
||||||
|
|
||||||
if (p_enable==simulating_motion)
|
|
||||||
return;
|
|
||||||
simulating_motion=p_enable;
|
|
||||||
|
|
||||||
if (p_enable) {
|
|
||||||
pre_xform = memnew( Matrix32 );
|
|
||||||
if (is_inside_scene())
|
|
||||||
*pre_xform=get_transform();
|
|
||||||
// query = Physics2DServer::get_singleton()->query_create(this,"_state_notify",Variant());
|
|
||||||
// Physics2DServer::get_singleton()->query_body_direct_state(query,get_rid());
|
|
||||||
Physics2DServer::get_singleton()->body_set_force_integration_callback(get_rid(),this,"_state_notify");
|
|
||||||
|
|
||||||
} else {
|
|
||||||
memdelete( pre_xform );
|
|
||||||
pre_xform=NULL;
|
|
||||||
Physics2DServer::get_singleton()->body_set_force_integration_callback(get_rid(),NULL,StringName());
|
|
||||||
pending=false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool StaticBody2D::is_simulating_motion() const {
|
|
||||||
|
|
||||||
return simulating_motion;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void StaticBody2D::set_friction(real_t p_friction){
|
void StaticBody2D::set_friction(real_t p_friction){
|
||||||
|
@ -194,10 +123,6 @@ real_t StaticBody2D::get_bounce() const{
|
||||||
|
|
||||||
void StaticBody2D::_bind_methods() {
|
void StaticBody2D::_bind_methods() {
|
||||||
|
|
||||||
ObjectTypeDB::bind_method(_MD("set_simulate_motion","enabled"),&StaticBody2D::set_simulate_motion);
|
|
||||||
ObjectTypeDB::bind_method(_MD("is_simulating_motion"),&StaticBody2D::is_simulating_motion);
|
|
||||||
ObjectTypeDB::bind_method(_MD("_update_xform"),&StaticBody2D::_update_xform);
|
|
||||||
ObjectTypeDB::bind_method(_MD("_state_notify"),&StaticBody2D::_state_notify);
|
|
||||||
ObjectTypeDB::bind_method(_MD("set_constant_linear_velocity","vel"),&StaticBody2D::set_constant_linear_velocity);
|
ObjectTypeDB::bind_method(_MD("set_constant_linear_velocity","vel"),&StaticBody2D::set_constant_linear_velocity);
|
||||||
ObjectTypeDB::bind_method(_MD("set_constant_angular_velocity","vel"),&StaticBody2D::set_constant_angular_velocity);
|
ObjectTypeDB::bind_method(_MD("set_constant_angular_velocity","vel"),&StaticBody2D::set_constant_angular_velocity);
|
||||||
ObjectTypeDB::bind_method(_MD("get_constant_linear_velocity"),&StaticBody2D::get_constant_linear_velocity);
|
ObjectTypeDB::bind_method(_MD("get_constant_linear_velocity"),&StaticBody2D::get_constant_linear_velocity);
|
||||||
|
@ -208,7 +133,6 @@ void StaticBody2D::_bind_methods() {
|
||||||
ObjectTypeDB::bind_method(_MD("set_bounce","bounce"),&StaticBody2D::set_bounce);
|
ObjectTypeDB::bind_method(_MD("set_bounce","bounce"),&StaticBody2D::set_bounce);
|
||||||
ObjectTypeDB::bind_method(_MD("get_bounce"),&StaticBody2D::get_bounce);
|
ObjectTypeDB::bind_method(_MD("get_bounce"),&StaticBody2D::get_bounce);
|
||||||
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"simulate_motion"),_SCS("set_simulate_motion"),_SCS("is_simulating_motion"));
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"constant_linear_velocity"),_SCS("set_constant_linear_velocity"),_SCS("get_constant_linear_velocity"));
|
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"constant_linear_velocity"),_SCS("set_constant_linear_velocity"),_SCS("get_constant_linear_velocity"));
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::REAL,"constant_angular_velocity"),_SCS("set_constant_angular_velocity"),_SCS("get_constant_angular_velocity"));
|
ADD_PROPERTY(PropertyInfo(Variant::REAL,"constant_angular_velocity"),_SCS("set_constant_angular_velocity"),_SCS("get_constant_angular_velocity"));
|
||||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_friction"),_SCS("get_friction"));
|
ADD_PROPERTY( PropertyInfo(Variant::REAL,"friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_friction"),_SCS("get_friction"));
|
||||||
|
@ -217,10 +141,6 @@ void StaticBody2D::_bind_methods() {
|
||||||
|
|
||||||
StaticBody2D::StaticBody2D() : PhysicsBody2D(Physics2DServer::BODY_MODE_STATIC) {
|
StaticBody2D::StaticBody2D() : PhysicsBody2D(Physics2DServer::BODY_MODE_STATIC) {
|
||||||
|
|
||||||
simulating_motion=false;
|
|
||||||
pre_xform=NULL;
|
|
||||||
setting=false;
|
|
||||||
pending=false;
|
|
||||||
constant_angular_velocity=0;
|
constant_angular_velocity=0;
|
||||||
bounce=0;
|
bounce=0;
|
||||||
friction=1;
|
friction=1;
|
||||||
|
@ -230,10 +150,6 @@ StaticBody2D::StaticBody2D() : PhysicsBody2D(Physics2DServer::BODY_MODE_STATIC)
|
||||||
|
|
||||||
StaticBody2D::~StaticBody2D() {
|
StaticBody2D::~StaticBody2D() {
|
||||||
|
|
||||||
if (pre_xform)
|
|
||||||
memdelete(pre_xform);
|
|
||||||
//if (query.is_valid())
|
|
||||||
// Physics2DServer::get_singleton()->free(query);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -385,7 +301,7 @@ void RigidBody2D::_direct_state_changed(Object *p_state) {
|
||||||
toadd[i].id=obj;
|
toadd[i].id=obj;
|
||||||
toadd[i].shape=shape;
|
toadd[i].shape=shape;
|
||||||
|
|
||||||
bool found=false;
|
// bool found=false;
|
||||||
|
|
||||||
Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.find(obj);
|
Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.find(obj);
|
||||||
if (!E) {
|
if (!E) {
|
||||||
|
@ -437,7 +353,8 @@ void RigidBody2D::_direct_state_changed(Object *p_state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
set_block_transform_notify(true); // don't want notify (would feedback loop)
|
set_block_transform_notify(true); // don't want notify (would feedback loop)
|
||||||
set_global_transform(state->get_transform());
|
if (mode!=MODE_KINEMATIC)
|
||||||
|
set_global_transform(state->get_transform());
|
||||||
linear_velocity=state->get_linear_velocity();
|
linear_velocity=state->get_linear_velocity();
|
||||||
angular_velocity=state->get_angular_velocity();
|
angular_velocity=state->get_angular_velocity();
|
||||||
active=!state->is_sleeping();
|
active=!state->is_sleeping();
|
||||||
|
@ -448,10 +365,6 @@ void RigidBody2D::_direct_state_changed(Object *p_state) {
|
||||||
state=NULL;
|
state=NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RigidBody2D::_notification(int p_what) {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void RigidBody2D::set_mode(Mode p_mode) {
|
void RigidBody2D::set_mode(Mode p_mode) {
|
||||||
|
|
||||||
|
@ -467,9 +380,9 @@ void RigidBody2D::set_mode(Mode p_mode) {
|
||||||
Physics2DServer::get_singleton()->body_set_mode(get_rid(),Physics2DServer::BODY_MODE_STATIC);
|
Physics2DServer::get_singleton()->body_set_mode(get_rid(),Physics2DServer::BODY_MODE_STATIC);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case MODE_STATIC_ACTIVE: {
|
case MODE_KINEMATIC: {
|
||||||
|
|
||||||
Physics2DServer::get_singleton()->body_set_mode(get_rid(),Physics2DServer::BODY_MODE_STATIC_ACTIVE);
|
Physics2DServer::get_singleton()->body_set_mode(get_rid(),Physics2DServer::BODY_MODE_KINEMATIC);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case MODE_CHARACTER: {
|
case MODE_CHARACTER: {
|
||||||
|
@ -643,16 +556,17 @@ Vector2 RigidBody2D::get_applied_force() const {
|
||||||
return Physics2DServer::get_singleton()->body_get_applied_force(get_rid());
|
return Physics2DServer::get_singleton()->body_get_applied_force(get_rid());
|
||||||
};
|
};
|
||||||
|
|
||||||
void RigidBody2D::set_use_continuous_collision_detection(bool p_enable) {
|
|
||||||
|
|
||||||
ccd=p_enable;
|
void RigidBody2D::set_continuous_collision_detection_mode(CCDMode p_mode) {
|
||||||
Physics2DServer::get_singleton()->body_set_enable_continuous_collision_detection(get_rid(),p_enable);
|
|
||||||
|
ccd_mode=p_mode;
|
||||||
|
Physics2DServer::get_singleton()->body_set_continuous_collision_detection_mode(get_rid(),Physics2DServer::CCDMode(p_mode));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RigidBody2D::is_using_continuous_collision_detection() const {
|
RigidBody2D::CCDMode RigidBody2D::get_continuous_collision_detection_mode() const {
|
||||||
|
|
||||||
|
return ccd_mode;
|
||||||
return ccd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -716,8 +630,8 @@ void RigidBody2D::_bind_methods() {
|
||||||
ObjectTypeDB::bind_method(_MD("set_contact_monitor","enabled"),&RigidBody2D::set_contact_monitor);
|
ObjectTypeDB::bind_method(_MD("set_contact_monitor","enabled"),&RigidBody2D::set_contact_monitor);
|
||||||
ObjectTypeDB::bind_method(_MD("is_contact_monitor_enabled"),&RigidBody2D::is_contact_monitor_enabled);
|
ObjectTypeDB::bind_method(_MD("is_contact_monitor_enabled"),&RigidBody2D::is_contact_monitor_enabled);
|
||||||
|
|
||||||
ObjectTypeDB::bind_method(_MD("set_use_continuous_collision_detection","enable"),&RigidBody2D::set_use_continuous_collision_detection);
|
ObjectTypeDB::bind_method(_MD("set_continuous_collision_detection_mode","mode"),&RigidBody2D::set_continuous_collision_detection_mode);
|
||||||
ObjectTypeDB::bind_method(_MD("is_using_continuous_collision_detection"),&RigidBody2D::is_using_continuous_collision_detection);
|
ObjectTypeDB::bind_method(_MD("get_continuous_collision_detection_mode"),&RigidBody2D::get_continuous_collision_detection_mode);
|
||||||
|
|
||||||
ObjectTypeDB::bind_method(_MD("set_axis_velocity","axis_velocity"),&RigidBody2D::set_axis_velocity);
|
ObjectTypeDB::bind_method(_MD("set_axis_velocity","axis_velocity"),&RigidBody2D::set_axis_velocity);
|
||||||
ObjectTypeDB::bind_method(_MD("apply_impulse","pos","impulse"),&RigidBody2D::apply_impulse);
|
ObjectTypeDB::bind_method(_MD("apply_impulse","pos","impulse"),&RigidBody2D::apply_impulse);
|
||||||
|
@ -737,13 +651,13 @@ void RigidBody2D::_bind_methods() {
|
||||||
|
|
||||||
BIND_VMETHOD(MethodInfo("_integrate_forces",PropertyInfo(Variant::OBJECT,"state:Physics2DDirectBodyState")));
|
BIND_VMETHOD(MethodInfo("_integrate_forces",PropertyInfo(Variant::OBJECT,"state:Physics2DDirectBodyState")));
|
||||||
|
|
||||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Rigid,Static,Character,Static Active"),_SCS("set_mode"),_SCS("get_mode"));
|
ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Rigid,Static,Character,Kinematic"),_SCS("set_mode"),_SCS("get_mode"));
|
||||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"mass",PROPERTY_HINT_EXP_RANGE,"0.01,65535,0.01"),_SCS("set_mass"),_SCS("get_mass"));
|
ADD_PROPERTY( PropertyInfo(Variant::REAL,"mass",PROPERTY_HINT_EXP_RANGE,"0.01,65535,0.01"),_SCS("set_mass"),_SCS("get_mass"));
|
||||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"weight",PROPERTY_HINT_EXP_RANGE,"0.01,65535,0.01",PROPERTY_USAGE_EDITOR),_SCS("set_weight"),_SCS("get_weight"));
|
ADD_PROPERTY( PropertyInfo(Variant::REAL,"weight",PROPERTY_HINT_EXP_RANGE,"0.01,65535,0.01",PROPERTY_USAGE_EDITOR),_SCS("set_weight"),_SCS("get_weight"));
|
||||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_friction"),_SCS("get_friction"));
|
ADD_PROPERTY( PropertyInfo(Variant::REAL,"friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_friction"),_SCS("get_friction"));
|
||||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_bounce"),_SCS("get_bounce"));
|
ADD_PROPERTY( PropertyInfo(Variant::REAL,"bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_bounce"),_SCS("get_bounce"));
|
||||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"custom_integrator"),_SCS("set_use_custom_integrator"),_SCS("is_using_custom_integrator"));
|
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"custom_integrator"),_SCS("set_use_custom_integrator"),_SCS("is_using_custom_integrator"));
|
||||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"continuous_cd"),_SCS("set_use_continuous_collision_detection"),_SCS("is_using_continuous_collision_detection"));
|
ADD_PROPERTY( PropertyInfo(Variant::INT,"continuous_cd",PROPERTY_HINT_ENUM,"Disabled,Cast Ray,Cast Shape"),_SCS("set_continuous_collision_detection_mode"),_SCS("get_continuous_collision_detection_mode"));
|
||||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"contacts_reported"),_SCS("set_max_contacts_reported"),_SCS("get_max_contacts_reported"));
|
ADD_PROPERTY( PropertyInfo(Variant::INT,"contacts_reported"),_SCS("set_max_contacts_reported"),_SCS("get_max_contacts_reported"));
|
||||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"contact_monitor"),_SCS("set_contact_monitor"),_SCS("is_contact_monitor_enabled"));
|
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"contact_monitor"),_SCS("set_contact_monitor"),_SCS("is_contact_monitor_enabled"));
|
||||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"active"),_SCS("set_active"),_SCS("is_active"));
|
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"active"),_SCS("set_active"),_SCS("is_active"));
|
||||||
|
@ -757,9 +671,14 @@ void RigidBody2D::_bind_methods() {
|
||||||
ADD_SIGNAL( MethodInfo("body_exit",PropertyInfo(Variant::OBJECT,"body")));
|
ADD_SIGNAL( MethodInfo("body_exit",PropertyInfo(Variant::OBJECT,"body")));
|
||||||
|
|
||||||
BIND_CONSTANT( MODE_STATIC );
|
BIND_CONSTANT( MODE_STATIC );
|
||||||
BIND_CONSTANT( MODE_STATIC_ACTIVE );
|
BIND_CONSTANT( MODE_KINEMATIC );
|
||||||
BIND_CONSTANT( MODE_RIGID );
|
BIND_CONSTANT( MODE_RIGID );
|
||||||
BIND_CONSTANT( MODE_CHARACTER );
|
BIND_CONSTANT( MODE_CHARACTER );
|
||||||
|
|
||||||
|
BIND_CONSTANT( CCD_MODE_DISABLED );
|
||||||
|
BIND_CONSTANT( CCD_MODE_CAST_RAY );
|
||||||
|
BIND_CONSTANT( CCD_MODE_CAST_SHAPE );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RigidBody2D::RigidBody2D() : PhysicsBody2D(Physics2DServer::BODY_MODE_RIGID) {
|
RigidBody2D::RigidBody2D() : PhysicsBody2D(Physics2DServer::BODY_MODE_RIGID) {
|
||||||
|
@ -774,7 +693,7 @@ RigidBody2D::RigidBody2D() : PhysicsBody2D(Physics2DServer::BODY_MODE_RIGID) {
|
||||||
|
|
||||||
angular_velocity=0;
|
angular_velocity=0;
|
||||||
active=true;
|
active=true;
|
||||||
ccd=false;
|
ccd_mode=CCD_MODE_DISABLED;
|
||||||
|
|
||||||
custom_integrator=false;
|
custom_integrator=false;
|
||||||
contact_monitor=NULL;
|
contact_monitor=NULL;
|
||||||
|
@ -790,5 +709,401 @@ RigidBody2D::~RigidBody2D() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
Variant KinematicBody2D::_get_collider() const {
|
||||||
|
|
||||||
|
ObjectID oid=get_collider();
|
||||||
|
if (oid==0)
|
||||||
|
return Variant();
|
||||||
|
Object *obj = ObjectDB::get_instance(oid);
|
||||||
|
if (!obj)
|
||||||
|
return Variant();
|
||||||
|
|
||||||
|
Reference *ref = obj->cast_to<Reference>();
|
||||||
|
if (ref) {
|
||||||
|
return Ref<Reference>(ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool KinematicBody2D::_ignores_mode(Physics2DServer::BodyMode p_mode) const {
|
||||||
|
|
||||||
|
switch(p_mode) {
|
||||||
|
case Physics2DServer::BODY_MODE_STATIC: return !collide_static;
|
||||||
|
case Physics2DServer::BODY_MODE_KINEMATIC: return !collide_kinematic;
|
||||||
|
case Physics2DServer::BODY_MODE_RIGID: return !collide_rigid;
|
||||||
|
case Physics2DServer::BODY_MODE_CHARACTER: return !collide_character;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KinematicBody2D::is_trapped() const {
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(!is_inside_scene(),false);
|
||||||
|
|
||||||
|
Physics2DDirectSpaceState *dss = Physics2DServer::get_singleton()->space_get_direct_state(get_world_2d()->get_space());
|
||||||
|
ERR_FAIL_COND_V(!dss,false);
|
||||||
|
|
||||||
|
const int max_shapes=32;
|
||||||
|
Physics2DDirectSpaceState::ShapeResult sr[max_shapes];
|
||||||
|
|
||||||
|
Set<RID> exclude;
|
||||||
|
exclude.insert(get_rid());
|
||||||
|
|
||||||
|
|
||||||
|
for(int i=0;i<get_shape_count();i++) {
|
||||||
|
|
||||||
|
|
||||||
|
int res = dss->intersect_shape(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i),Vector2(),sr,max_shapes,exclude);
|
||||||
|
|
||||||
|
for(int j=0;j<res;j++) {
|
||||||
|
|
||||||
|
Physics2DServer::BodyMode bm = Physics2DServer::get_singleton()->body_get_mode(sr[j].rid);
|
||||||
|
if (!_ignores_mode(bm)) {
|
||||||
|
return true; //it's indeed trapped
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
void KinematicBody2D::untrap() {
|
||||||
|
|
||||||
|
//this is reaaaaaaaaally wild, will probably only work for simple cases
|
||||||
|
ERR_FAIL_COND(!is_inside_scene());
|
||||||
|
|
||||||
|
Physics2DDirectSpaceState *dss = Physics2DServer::get_singleton()->space_get_direct_state(get_world_2d()->get_space());
|
||||||
|
ERR_FAIL_COND(!dss);
|
||||||
|
|
||||||
|
const int max_shapes=32;
|
||||||
|
Physics2DDirectSpaceState::ShapeResult sr[max_shapes];
|
||||||
|
const int max_contacts=8;
|
||||||
|
Vector2 pairs[max_contacts*2];
|
||||||
|
|
||||||
|
Set<RID> exclude;
|
||||||
|
exclude.insert(get_rid());
|
||||||
|
|
||||||
|
Vector2 untrap_vec;
|
||||||
|
|
||||||
|
for(int i=0;i<get_shape_count();i++) {
|
||||||
|
|
||||||
|
Matrix32 shape_xform = get_global_transform() * get_shape_transform(i);
|
||||||
|
int res = dss->intersect_shape(get_shape(i)->get_rid(), shape_xform,Vector2(),sr,max_shapes,exclude);
|
||||||
|
|
||||||
|
for(int j=0;j<res;j++) {
|
||||||
|
|
||||||
|
Physics2DServer::BodyMode bm = Physics2DServer::get_singleton()->body_get_mode(sr[j].rid);
|
||||||
|
if (_ignores_mode(bm)) {
|
||||||
|
exclude.insert(sr[j].rid);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
int rc;
|
||||||
|
bool c = Physics2DServer::get_singleton()->body_collide_shape(sr[j].rid,sr[j].shape,get_shape(i)->get_rid(),shape_xform,Vector2(),pairs,max_contacts,rc);
|
||||||
|
|
||||||
|
if (c) {
|
||||||
|
|
||||||
|
for(int k=0;k<rc;k++) {
|
||||||
|
|
||||||
|
untrap_vec+=pairs[k*2+0]-pairs[k*2+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
untrap_vec += untrap_vec.normalized()*margin;
|
||||||
|
|
||||||
|
|
||||||
|
Matrix32 gt = get_global_transform();
|
||||||
|
gt.elements[2]+=untrap_vec;
|
||||||
|
set_global_transform(gt);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 KinematicBody2D::move(const Vector2& p_motion) {
|
||||||
|
|
||||||
|
colliding=false;
|
||||||
|
ERR_FAIL_COND_V(!is_inside_scene(),Vector2());
|
||||||
|
Physics2DDirectSpaceState *dss = Physics2DServer::get_singleton()->space_get_direct_state(get_world_2d()->get_space());
|
||||||
|
ERR_FAIL_COND_V(!dss,Vector2());
|
||||||
|
const int max_shapes=32;
|
||||||
|
Physics2DDirectSpaceState::ShapeResult sr[max_shapes];
|
||||||
|
|
||||||
|
float best_travel = 1e20;
|
||||||
|
Physics2DDirectSpaceState::MotionCastCollision mcc_final;
|
||||||
|
Set<RID> exclude;
|
||||||
|
exclude.insert(get_rid());
|
||||||
|
|
||||||
|
print_line("pos: "+get_global_pos());
|
||||||
|
print_line("mlen: "+p_motion);
|
||||||
|
|
||||||
|
if (!collide_static || ! collide_rigid || !collide_character || !collide_kinematic) {
|
||||||
|
//fill exclude list..
|
||||||
|
for(int i=0;i<get_shape_count();i++) {
|
||||||
|
|
||||||
|
|
||||||
|
int res = dss->intersect_shape(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i),p_motion,sr,max_shapes,exclude);
|
||||||
|
|
||||||
|
for(int j=0;j<res;j++) {
|
||||||
|
|
||||||
|
Physics2DServer::BodyMode bm = Physics2DServer::get_singleton()->body_get_mode(sr[j].rid);
|
||||||
|
if (_ignores_mode(bm)) {
|
||||||
|
exclude.insert(sr[j].rid);
|
||||||
|
} else {
|
||||||
|
// print_line("DANGER???");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=0;i<get_shape_count();i++) {
|
||||||
|
|
||||||
|
Physics2DDirectSpaceState::MotionCastCollision mcc;
|
||||||
|
|
||||||
|
bool res = dss->cast_motion(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i), p_motion, mcc,exclude,0);
|
||||||
|
if (res==false)
|
||||||
|
continue;
|
||||||
|
if (mcc.travel<=0) {
|
||||||
|
//uh it's trapped
|
||||||
|
colliding=false;
|
||||||
|
return p_motion;
|
||||||
|
}
|
||||||
|
if (mcc.travel < best_travel) {
|
||||||
|
|
||||||
|
mcc_final=mcc;
|
||||||
|
best_travel=mcc.travel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float motion;
|
||||||
|
Vector2 motion_ret;
|
||||||
|
Vector2 push;
|
||||||
|
if (best_travel>1) {
|
||||||
|
//not collided
|
||||||
|
colliding=false;
|
||||||
|
motion=p_motion.length(); //no stopped
|
||||||
|
} else {
|
||||||
|
|
||||||
|
colliding=true;
|
||||||
|
collision=mcc_final.point;
|
||||||
|
normal=mcc_final.normal;
|
||||||
|
collider=mcc_final.collider_id;
|
||||||
|
Vector2 mnormal=p_motion.normalized();
|
||||||
|
|
||||||
|
float sine = Math::abs(mnormal.dot(normal));
|
||||||
|
float retreat=0;
|
||||||
|
motion = p_motion.length()*mcc_final.travel;
|
||||||
|
|
||||||
|
if (sine==0) {
|
||||||
|
//something odd going on, do not allow motion?
|
||||||
|
|
||||||
|
retreat=motion;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
retreat = margin/sine;
|
||||||
|
if (retreat>motion)
|
||||||
|
retreat=motion;
|
||||||
|
}
|
||||||
|
|
||||||
|
motion_ret=p_motion.normalized() * ( p_motion.length() - motion);
|
||||||
|
motion-=retreat;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Matrix32 gt = get_global_transform();
|
||||||
|
gt.elements[2]+=p_motion.normalized()*motion;
|
||||||
|
set_global_transform(gt);
|
||||||
|
|
||||||
|
return motion_ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 KinematicBody2D::move_to(const Vector2& p_position) {
|
||||||
|
|
||||||
|
return move(p_position-get_global_pos());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KinematicBody2D::can_move_to(const Vector2& p_position) {
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(!is_inside_scene(),false);
|
||||||
|
Physics2DDirectSpaceState *dss = Physics2DServer::get_singleton()->space_get_direct_state(get_world_2d()->get_space());
|
||||||
|
ERR_FAIL_COND_V(!dss,false);
|
||||||
|
|
||||||
|
const int max_shapes=32;
|
||||||
|
Physics2DDirectSpaceState::ShapeResult sr[max_shapes];
|
||||||
|
|
||||||
|
Vector2 motion = p_position-get_global_pos();
|
||||||
|
|
||||||
|
Physics2DDirectSpaceState::MotionCastCollision mcc_final;
|
||||||
|
Set<RID> exclude;
|
||||||
|
exclude.insert(get_rid());
|
||||||
|
|
||||||
|
//fill exclude list..
|
||||||
|
for(int i=0;i<get_shape_count();i++) {
|
||||||
|
|
||||||
|
|
||||||
|
int res = dss->intersect_shape(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i),motion,sr,max_shapes,exclude);
|
||||||
|
|
||||||
|
for(int j=0;j<res;j++) {
|
||||||
|
|
||||||
|
Physics2DServer::BodyMode bm = Physics2DServer::get_singleton()->body_get_mode(sr[j].rid);
|
||||||
|
if (_ignores_mode(bm)) {
|
||||||
|
exclude.insert(sr[j].rid);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; //omg collided
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KinematicBody2D::is_colliding() const {
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(!is_inside_scene(),false);
|
||||||
|
|
||||||
|
return colliding;
|
||||||
|
}
|
||||||
|
Vector2 KinematicBody2D::get_collision_pos() const {
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(!colliding,Vector2());
|
||||||
|
return collision;
|
||||||
|
|
||||||
|
}
|
||||||
|
Vector2 KinematicBody2D::get_collision_normal() const {
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(!colliding,Vector2());
|
||||||
|
return normal;
|
||||||
|
|
||||||
|
}
|
||||||
|
ObjectID KinematicBody2D::get_collider() const {
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(!colliding,0);
|
||||||
|
return collider;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KinematicBody2D::set_collide_with_static_bodies(bool p_enable) {
|
||||||
|
|
||||||
|
collide_static=p_enable;
|
||||||
|
}
|
||||||
|
bool KinematicBody2D::can_collide_with_static_bodies() const {
|
||||||
|
|
||||||
|
return collide_static;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KinematicBody2D::set_collide_with_rigid_bodies(bool p_enable) {
|
||||||
|
|
||||||
|
collide_rigid=p_enable;
|
||||||
|
|
||||||
|
}
|
||||||
|
bool KinematicBody2D::can_collide_with_rigid_bodies() const {
|
||||||
|
|
||||||
|
|
||||||
|
return collide_rigid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KinematicBody2D::set_collide_with_kinematic_bodies(bool p_enable) {
|
||||||
|
|
||||||
|
collide_kinematic=p_enable;
|
||||||
|
|
||||||
|
}
|
||||||
|
bool KinematicBody2D::can_collide_with_kinematic_bodies() const {
|
||||||
|
|
||||||
|
return collide_kinematic;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KinematicBody2D::set_collide_with_character_bodies(bool p_enable) {
|
||||||
|
|
||||||
|
collide_character=p_enable;
|
||||||
|
}
|
||||||
|
bool KinematicBody2D::can_collide_with_character_bodies() const {
|
||||||
|
|
||||||
|
return collide_character;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KinematicBody2D::set_collision_margin(float p_margin) {
|
||||||
|
|
||||||
|
margin=p_margin;
|
||||||
|
}
|
||||||
|
|
||||||
|
float KinematicBody2D::get_collision_margin() const{
|
||||||
|
|
||||||
|
return margin;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KinematicBody2D::_bind_methods() {
|
||||||
|
|
||||||
|
|
||||||
|
ObjectTypeDB::bind_method(_MD("is_trapped"),&KinematicBody2D::is_trapped);
|
||||||
|
ObjectTypeDB::bind_method(_MD("untrap"),&KinematicBody2D::untrap);
|
||||||
|
|
||||||
|
ObjectTypeDB::bind_method(_MD("move","rel_vec"),&KinematicBody2D::move);
|
||||||
|
ObjectTypeDB::bind_method(_MD("move_to","position"),&KinematicBody2D::move_to);
|
||||||
|
|
||||||
|
ObjectTypeDB::bind_method(_MD("can_move_to","position"),&KinematicBody2D::can_move_to);
|
||||||
|
|
||||||
|
ObjectTypeDB::bind_method(_MD("is_colliding"),&KinematicBody2D::is_colliding);
|
||||||
|
|
||||||
|
ObjectTypeDB::bind_method(_MD("get_collision_pos"),&KinematicBody2D::get_collision_pos);
|
||||||
|
ObjectTypeDB::bind_method(_MD("get_collision_normal"),&KinematicBody2D::get_collision_normal);
|
||||||
|
ObjectTypeDB::bind_method(_MD("get_collider:Object"),&KinematicBody2D::get_collider);
|
||||||
|
|
||||||
|
|
||||||
|
ObjectTypeDB::bind_method(_MD("set_collide_with_static_bodies","enable"),&KinematicBody2D::set_collide_with_static_bodies);
|
||||||
|
ObjectTypeDB::bind_method(_MD("can_collide_with_static_bodies"),&KinematicBody2D::can_collide_with_static_bodies);
|
||||||
|
|
||||||
|
ObjectTypeDB::bind_method(_MD("set_collide_with_kinematic_bodies","enable"),&KinematicBody2D::set_collide_with_kinematic_bodies);
|
||||||
|
ObjectTypeDB::bind_method(_MD("can_collide_with_kinematic_bodies"),&KinematicBody2D::can_collide_with_kinematic_bodies);
|
||||||
|
|
||||||
|
ObjectTypeDB::bind_method(_MD("set_collide_with_rigid_bodies","enable"),&KinematicBody2D::set_collide_with_rigid_bodies);
|
||||||
|
ObjectTypeDB::bind_method(_MD("can_collide_with_rigid_bodies"),&KinematicBody2D::can_collide_with_rigid_bodies);
|
||||||
|
|
||||||
|
ObjectTypeDB::bind_method(_MD("set_collide_with_character_bodies","enable"),&KinematicBody2D::set_collide_with_character_bodies);
|
||||||
|
ObjectTypeDB::bind_method(_MD("can_collide_with_character_bodies"),&KinematicBody2D::can_collide_with_character_bodies);
|
||||||
|
|
||||||
|
ObjectTypeDB::bind_method(_MD("set_collision_margin","pixels"),&KinematicBody2D::set_collision_margin);
|
||||||
|
ObjectTypeDB::bind_method(_MD("get_collision_margin","pixels"),&KinematicBody2D::get_collision_margin);
|
||||||
|
|
||||||
|
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collide_with/static"),_SCS("set_collide_with_static_bodies"),_SCS("can_collide_with_static_bodies"));
|
||||||
|
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collide_with/kinematic"),_SCS("set_collide_with_kinematic_bodies"),_SCS("can_collide_with_kinematic_bodies"));
|
||||||
|
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collide_with/rigid"),_SCS("set_collide_with_rigid_bodies"),_SCS("can_collide_with_rigid_bodies"));
|
||||||
|
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"collide_with/character"),_SCS("set_collide_with_character_bodies"),_SCS("can_collide_with_character_bodies"));
|
||||||
|
ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/margin",PROPERTY_HINT_RANGE,"0.01,256,0.01"),_SCS("set_collision_margin"),_SCS("get_collision_margin"));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
KinematicBody2D::KinematicBody2D() : PhysicsBody2D(Physics2DServer::BODY_MODE_KINEMATIC){
|
||||||
|
|
||||||
|
collide_static=true;
|
||||||
|
collide_rigid=true;
|
||||||
|
collide_kinematic=true;
|
||||||
|
collide_character=true;
|
||||||
|
|
||||||
|
colliding=false;
|
||||||
|
collider=0;
|
||||||
|
|
||||||
|
margin=1;
|
||||||
|
}
|
||||||
|
KinematicBody2D::~KinematicBody2D() {
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,15 +52,8 @@ class StaticBody2D : public PhysicsBody2D {
|
||||||
|
|
||||||
OBJ_TYPE(StaticBody2D,PhysicsBody2D);
|
OBJ_TYPE(StaticBody2D,PhysicsBody2D);
|
||||||
|
|
||||||
Matrix32 *pre_xform;
|
|
||||||
//RID query;
|
|
||||||
bool setting;
|
|
||||||
bool pending;
|
|
||||||
bool simulating_motion;
|
|
||||||
Vector2 constant_linear_velocity;
|
Vector2 constant_linear_velocity;
|
||||||
real_t constant_angular_velocity;
|
real_t constant_angular_velocity;
|
||||||
void _update_xform();
|
|
||||||
void _state_notify(Object *p_object);
|
|
||||||
|
|
||||||
real_t bounce;
|
real_t bounce;
|
||||||
real_t friction;
|
real_t friction;
|
||||||
|
@ -68,7 +61,6 @@ class StaticBody2D : public PhysicsBody2D {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void _notification(int p_what);
|
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -79,8 +71,6 @@ public:
|
||||||
void set_bounce(real_t p_bounce);
|
void set_bounce(real_t p_bounce);
|
||||||
real_t get_bounce() const;
|
real_t get_bounce() const;
|
||||||
|
|
||||||
void set_simulate_motion(bool p_enable);
|
|
||||||
bool is_simulating_motion() const;
|
|
||||||
|
|
||||||
void set_constant_linear_velocity(const Vector2& p_vel);
|
void set_constant_linear_velocity(const Vector2& p_vel);
|
||||||
void set_constant_angular_velocity(real_t p_vel);
|
void set_constant_angular_velocity(real_t p_vel);
|
||||||
|
@ -102,8 +92,15 @@ public:
|
||||||
MODE_RIGID,
|
MODE_RIGID,
|
||||||
MODE_STATIC,
|
MODE_STATIC,
|
||||||
MODE_CHARACTER,
|
MODE_CHARACTER,
|
||||||
MODE_STATIC_ACTIVE,
|
MODE_KINEMATIC,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum CCDMode {
|
||||||
|
CCD_MODE_DISABLED,
|
||||||
|
CCD_MODE_CAST_RAY,
|
||||||
|
CCD_MODE_CAST_SHAPE,
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool can_sleep;
|
bool can_sleep;
|
||||||
|
@ -117,13 +114,14 @@ private:
|
||||||
Vector2 linear_velocity;
|
Vector2 linear_velocity;
|
||||||
real_t angular_velocity;
|
real_t angular_velocity;
|
||||||
bool active;
|
bool active;
|
||||||
bool ccd;
|
|
||||||
|
|
||||||
|
|
||||||
int max_contacts_reported;
|
int max_contacts_reported;
|
||||||
|
|
||||||
bool custom_integrator;
|
bool custom_integrator;
|
||||||
|
|
||||||
|
CCDMode ccd_mode;
|
||||||
|
|
||||||
|
|
||||||
struct ShapePair {
|
struct ShapePair {
|
||||||
|
|
||||||
|
@ -173,7 +171,6 @@ private:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void _notification(int p_what);
|
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -215,8 +212,8 @@ public:
|
||||||
void set_max_contacts_reported(int p_amount);
|
void set_max_contacts_reported(int p_amount);
|
||||||
int get_max_contacts_reported() const;
|
int get_max_contacts_reported() const;
|
||||||
|
|
||||||
void set_use_continuous_collision_detection(bool p_enable);
|
void set_continuous_collision_detection_mode(CCDMode p_mode);
|
||||||
bool is_using_continuous_collision_detection() const;
|
CCDMode get_continuous_collision_detection_mode() const;
|
||||||
|
|
||||||
void apply_impulse(const Vector2& p_pos, const Vector2& p_impulse);
|
void apply_impulse(const Vector2& p_pos, const Vector2& p_impulse);
|
||||||
|
|
||||||
|
@ -229,4 +226,65 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
VARIANT_ENUM_CAST(RigidBody2D::Mode);
|
VARIANT_ENUM_CAST(RigidBody2D::Mode);
|
||||||
|
VARIANT_ENUM_CAST(RigidBody2D::CCDMode);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class KinematicBody2D : public PhysicsBody2D {
|
||||||
|
|
||||||
|
OBJ_TYPE(KinematicBody2D,PhysicsBody2D);
|
||||||
|
|
||||||
|
float margin;
|
||||||
|
bool collide_static;
|
||||||
|
bool collide_rigid;
|
||||||
|
bool collide_kinematic;
|
||||||
|
bool collide_character;
|
||||||
|
|
||||||
|
bool colliding;
|
||||||
|
Vector2 collision;
|
||||||
|
Vector2 normal;
|
||||||
|
ObjectID collider;
|
||||||
|
|
||||||
|
|
||||||
|
Variant _get_collider() const;
|
||||||
|
|
||||||
|
_FORCE_INLINE_ bool _ignores_mode(Physics2DServer::BodyMode) const;
|
||||||
|
protected:
|
||||||
|
|
||||||
|
static void _bind_methods();
|
||||||
|
public:
|
||||||
|
|
||||||
|
bool is_trapped() const;
|
||||||
|
void untrap();
|
||||||
|
|
||||||
|
Vector2 move(const Vector2& p_motion);
|
||||||
|
Vector2 move_to(const Vector2& p_position);
|
||||||
|
|
||||||
|
bool can_move_to(const Vector2& p_position);
|
||||||
|
bool is_colliding() const;
|
||||||
|
Vector2 get_collision_pos() const;
|
||||||
|
Vector2 get_collision_normal() const;
|
||||||
|
ObjectID get_collider() const;
|
||||||
|
|
||||||
|
void set_collide_with_static_bodies(bool p_enable);
|
||||||
|
bool can_collide_with_static_bodies() const;
|
||||||
|
|
||||||
|
void set_collide_with_rigid_bodies(bool p_enable);
|
||||||
|
bool can_collide_with_rigid_bodies() const;
|
||||||
|
|
||||||
|
void set_collide_with_kinematic_bodies(bool p_enable);
|
||||||
|
bool can_collide_with_kinematic_bodies() const;
|
||||||
|
|
||||||
|
void set_collide_with_character_bodies(bool p_enable);
|
||||||
|
bool can_collide_with_character_bodies() const;
|
||||||
|
|
||||||
|
void set_collision_margin(float p_margin);
|
||||||
|
float get_collision_margin() const;
|
||||||
|
|
||||||
|
KinematicBody2D();
|
||||||
|
~KinematicBody2D();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // PHYSICS_BODY_2D_H
|
#endif // PHYSICS_BODY_2D_H
|
||||||
|
|
|
@ -105,7 +105,7 @@ void Sprite::set_texture(const Ref<Texture>& p_texture) {
|
||||||
}
|
}
|
||||||
texture=p_texture;
|
texture=p_texture;
|
||||||
if (texture.is_valid()) {
|
if (texture.is_valid()) {
|
||||||
texture->set_flags(texture->get_flags()&(~Texture::FLAG_REPEAT)); //remove repeat from texture, it looks bad in sprites
|
texture->set_flags(texture->get_flags()); //remove repeat from texture, it looks bad in sprites
|
||||||
texture->connect(CoreStringNames::get_singleton()->changed,this,SceneStringNames::get_singleton()->update);
|
texture->connect(CoreStringNames::get_singleton()->changed,this,SceneStringNames::get_singleton()->update);
|
||||||
}
|
}
|
||||||
update();
|
update();
|
||||||
|
|
|
@ -181,7 +181,7 @@ void TileMap::_update_dirty_quadrants() {
|
||||||
if (!tile_set->has_tile(c.id))
|
if (!tile_set->has_tile(c.id))
|
||||||
continue;
|
continue;
|
||||||
Ref<Texture> tex = tile_set->tile_get_texture(c.id);
|
Ref<Texture> tex = tile_set->tile_get_texture(c.id);
|
||||||
Vector2 tile_ofs = tile_set->tile_get_offset(c.id);
|
Vector2 tile_ofs = tile_set->tile_get_texture_offset(c.id);
|
||||||
|
|
||||||
Vector2 offset = Point2( E->key().x, E->key().y )*cell_size - q.pos;
|
Vector2 offset = Point2( E->key().x, E->key().y )*cell_size - q.pos;
|
||||||
|
|
||||||
|
@ -215,6 +215,7 @@ void TileMap::_update_dirty_quadrants() {
|
||||||
rect.size.y=-rect.size.y;
|
rect.size.y=-rect.size.y;
|
||||||
|
|
||||||
|
|
||||||
|
rect.pos+=tile_ofs;
|
||||||
if (r==Rect2()) {
|
if (r==Rect2()) {
|
||||||
|
|
||||||
tex->draw_rect(q.canvas_item,rect);
|
tex->draw_rect(q.canvas_item,rect);
|
||||||
|
@ -231,8 +232,9 @@ void TileMap::_update_dirty_quadrants() {
|
||||||
Ref<Shape2D> shape = shapes[i];
|
Ref<Shape2D> shape = shapes[i];
|
||||||
if (shape.is_valid()) {
|
if (shape.is_valid()) {
|
||||||
|
|
||||||
|
Vector2 shape_ofs = tile_set->tile_get_shape_offset(c.id);
|
||||||
Matrix32 xform;
|
Matrix32 xform;
|
||||||
xform.set_origin(offset.floor());
|
xform.set_origin(offset.floor()+shape_ofs);
|
||||||
if (c.flip_h) {
|
if (c.flip_h) {
|
||||||
xform.elements[0]=-xform.elements[0];
|
xform.elements[0]=-xform.elements[0];
|
||||||
xform.elements[2].x+=s.x;
|
xform.elements[2].x+=s.x;
|
||||||
|
@ -242,6 +244,7 @@ void TileMap::_update_dirty_quadrants() {
|
||||||
xform.elements[2].y+=s.y;
|
xform.elements[2].y+=s.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ps->body_add_shape(q.static_body,shape->get_rid(),xform);
|
ps->body_add_shape(q.static_body,shape->get_rid(),xform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -434,9 +434,9 @@ void RigidBody::set_mode(Mode p_mode) {
|
||||||
PhysicsServer::get_singleton()->body_set_mode(get_rid(),PhysicsServer::BODY_MODE_CHARACTER);
|
PhysicsServer::get_singleton()->body_set_mode(get_rid(),PhysicsServer::BODY_MODE_CHARACTER);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case MODE_STATIC_ACTIVE: {
|
case MODE_KINEMATIC: {
|
||||||
|
|
||||||
PhysicsServer::get_singleton()->body_set_mode(get_rid(),PhysicsServer::BODY_MODE_STATIC_ACTIVE);
|
PhysicsServer::get_singleton()->body_set_mode(get_rid(),PhysicsServer::BODY_MODE_KINEMATIC);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -684,7 +684,7 @@ void RigidBody::_bind_methods() {
|
||||||
|
|
||||||
BIND_VMETHOD(MethodInfo("_integrate_forces",PropertyInfo(Variant::OBJECT,"state:PhysicsDirectBodyState")));
|
BIND_VMETHOD(MethodInfo("_integrate_forces",PropertyInfo(Variant::OBJECT,"state:PhysicsDirectBodyState")));
|
||||||
|
|
||||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Rigid,Static,Character,Static Active"),_SCS("set_mode"),_SCS("get_mode"));
|
ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Rigid,Static,Character,Kinematic"),_SCS("set_mode"),_SCS("get_mode"));
|
||||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"mass",PROPERTY_HINT_EXP_RANGE,"0.01,65535,0.01"),_SCS("set_mass"),_SCS("get_mass"));
|
ADD_PROPERTY( PropertyInfo(Variant::REAL,"mass",PROPERTY_HINT_EXP_RANGE,"0.01,65535,0.01"),_SCS("set_mass"),_SCS("get_mass"));
|
||||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"weight",PROPERTY_HINT_EXP_RANGE,"0.01,65535,0.01",PROPERTY_USAGE_EDITOR),_SCS("set_weight"),_SCS("get_weight"));
|
ADD_PROPERTY( PropertyInfo(Variant::REAL,"weight",PROPERTY_HINT_EXP_RANGE,"0.01,65535,0.01",PROPERTY_USAGE_EDITOR),_SCS("set_weight"),_SCS("get_weight"));
|
||||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_friction"),_SCS("get_friction"));
|
ADD_PROPERTY( PropertyInfo(Variant::REAL,"friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_friction"),_SCS("get_friction"));
|
||||||
|
@ -704,7 +704,7 @@ void RigidBody::_bind_methods() {
|
||||||
ADD_SIGNAL( MethodInfo("body_exit",PropertyInfo(Variant::OBJECT,"body")));
|
ADD_SIGNAL( MethodInfo("body_exit",PropertyInfo(Variant::OBJECT,"body")));
|
||||||
|
|
||||||
BIND_CONSTANT( MODE_STATIC );
|
BIND_CONSTANT( MODE_STATIC );
|
||||||
BIND_CONSTANT( MODE_STATIC_ACTIVE );
|
BIND_CONSTANT( MODE_KINEMATIC );
|
||||||
BIND_CONSTANT( MODE_RIGID );
|
BIND_CONSTANT( MODE_RIGID );
|
||||||
BIND_CONSTANT( MODE_CHARACTER );
|
BIND_CONSTANT( MODE_CHARACTER );
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ public:
|
||||||
MODE_RIGID,
|
MODE_RIGID,
|
||||||
MODE_STATIC,
|
MODE_STATIC,
|
||||||
MODE_CHARACTER,
|
MODE_CHARACTER,
|
||||||
MODE_STATIC_ACTIVE,
|
MODE_KINEMATIC,
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -135,7 +135,7 @@ RES ResourceFormatLoaderImage::load(const String &p_path,const String& p_origina
|
||||||
flags|=Texture::FLAG_FILTER;
|
flags|=Texture::FLAG_FILTER;
|
||||||
if (bool(GLOBAL_DEF("texture_import/gen_mipmaps",true)))
|
if (bool(GLOBAL_DEF("texture_import/gen_mipmaps",true)))
|
||||||
flags|=Texture::FLAG_MIPMAPS;
|
flags|=Texture::FLAG_MIPMAPS;
|
||||||
if (bool(GLOBAL_DEF("texture_import/repeat",true)))
|
if (bool(GLOBAL_DEF("texture_import/repeat",false)))
|
||||||
flags|=Texture::FLAG_REPEAT;
|
flags|=Texture::FLAG_REPEAT;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -452,6 +452,7 @@ void register_scene_types() {
|
||||||
ObjectTypeDB::register_virtual_type<PhysicsBody2D>();
|
ObjectTypeDB::register_virtual_type<PhysicsBody2D>();
|
||||||
ObjectTypeDB::register_type<StaticBody2D>();
|
ObjectTypeDB::register_type<StaticBody2D>();
|
||||||
ObjectTypeDB::register_type<RigidBody2D>();
|
ObjectTypeDB::register_type<RigidBody2D>();
|
||||||
|
//ObjectTypeDB::register_type<KinematicBody2D>();
|
||||||
ObjectTypeDB::register_type<Area2D>();
|
ObjectTypeDB::register_type<Area2D>();
|
||||||
ObjectTypeDB::register_type<CollisionShape2D>();
|
ObjectTypeDB::register_type<CollisionShape2D>();
|
||||||
ObjectTypeDB::register_type<CollisionPolygon2D>();
|
ObjectTypeDB::register_type<CollisionPolygon2D>();
|
||||||
|
|
|
@ -47,20 +47,82 @@ real_t Shape2D::get_custom_solver_bias() const{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Shape2D::collide_with_motion(const Matrix32& p_local_xform, const Vector2& p_local_motion, const Ref<Shape2D>& p_shape, const Matrix32& p_shape_xform, const Vector2 &p_shape_motion) {
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(p_shape.is_null(),false);
|
||||||
|
int r;
|
||||||
|
return Physics2DServer::get_singleton()->shape_collide(get_rid(),p_local_xform,p_local_motion,p_shape->get_rid(),p_shape_xform,p_shape_motion,NULL,0,r);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Shape2D::collide(const Matrix32& p_local_xform, const Ref<Shape2D>& p_shape, const Matrix32& p_shape_xform){
|
||||||
|
ERR_FAIL_COND_V(p_shape.is_null(),false);
|
||||||
|
int r;
|
||||||
|
return Physics2DServer::get_singleton()->shape_collide(get_rid(),p_local_xform,Vector2(),p_shape->get_rid(),p_shape_xform,Vector2(),NULL,0,r);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Variant Shape2D::collide_with_motion_and_get_contacts(const Matrix32& p_local_xform, const Vector2& p_local_motion, const Ref<Shape2D>& p_shape, const Matrix32& p_shape_xform, const Vector2 &p_shape_motion){
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(p_shape.is_null(),Variant());
|
||||||
|
const int max_contacts = 16;
|
||||||
|
Vector2 result[max_contacts*2];
|
||||||
|
int contacts=0;
|
||||||
|
|
||||||
|
if (!Physics2DServer::get_singleton()->shape_collide(get_rid(),p_local_xform,p_local_motion,p_shape->get_rid(),p_shape_xform,p_shape_motion,result,max_contacts,contacts))
|
||||||
|
return Variant();
|
||||||
|
|
||||||
|
Array results;
|
||||||
|
results.resize(contacts*2);
|
||||||
|
for(int i=0;i<contacts;i++) {
|
||||||
|
results[i]=result[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
|
||||||
|
}
|
||||||
|
Variant Shape2D::collide_and_get_contacts(const Matrix32& p_local_xform, const Ref<Shape2D>& p_shape, const Matrix32& p_shape_xform){
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(p_shape.is_null(),Variant());
|
||||||
|
const int max_contacts = 16;
|
||||||
|
Vector2 result[max_contacts*2];
|
||||||
|
int contacts=0;
|
||||||
|
|
||||||
|
if (!Physics2DServer::get_singleton()->shape_collide(get_rid(),p_local_xform,Vector2(),p_shape->get_rid(),p_shape_xform,Vector2(),result,max_contacts,contacts))
|
||||||
|
return Variant();
|
||||||
|
|
||||||
|
Array results;
|
||||||
|
results.resize(contacts*2);
|
||||||
|
for(int i=0;i<contacts;i++) {
|
||||||
|
results[i]=result[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void Shape2D::_bind_methods() {
|
void Shape2D::_bind_methods() {
|
||||||
|
|
||||||
ObjectTypeDB::bind_method(_MD("set_custom_solver_bias","bias"),&Shape2D::set_custom_solver_bias);
|
ObjectTypeDB::bind_method(_MD("set_custom_solver_bias","bias"),&Shape2D::set_custom_solver_bias);
|
||||||
ObjectTypeDB::bind_method(_MD("get_custom_solver_bias"),&Shape2D::get_custom_solver_bias);
|
ObjectTypeDB::bind_method(_MD("get_custom_solver_bias"),&Shape2D::get_custom_solver_bias);
|
||||||
|
ObjectTypeDB::bind_method(_MD("collide","local_xform","with_shape:Shape2D","shape_xform"),&Shape2D::collide);
|
||||||
|
ObjectTypeDB::bind_method(_MD("collide_with_motion","local_xform","local_motion","with_shape:Shape2D","shape_xform","shape_motion"),&Shape2D::collide_with_motion);
|
||||||
|
ObjectTypeDB::bind_method(_MD("collide_and_get_contacts:var","local_xform","with_shape:Shape2D","shape_xform"),&Shape2D::collide_and_get_contacts);
|
||||||
|
ObjectTypeDB::bind_method(_MD("collide_with_motion_and_get_contacts:var","local_xform","local_motion","with_shape:Shape2D","shape_xform","shape_motion"),&Shape2D::collide_and_get_contacts);
|
||||||
|
|
||||||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"custom_solver_bias",PROPERTY_HINT_RANGE,"0,1,0.001"),_SCS("set_custom_solver_bias"),_SCS("get_custom_solver_bias"));
|
ADD_PROPERTY( PropertyInfo(Variant::REAL,"custom_solver_bias",PROPERTY_HINT_RANGE,"0,1,0.001"),_SCS("set_custom_solver_bias"),_SCS("get_custom_solver_bias"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Shape2D::Shape2D(const RID& p_rid) {
|
Shape2D::Shape2D(const RID& p_rid) {
|
||||||
shape=p_rid;
|
shape=p_rid;
|
||||||
custom_bias=0;
|
custom_bias=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Shape2D::~Shape2D() {
|
Shape2D::~Shape2D() {
|
||||||
|
|
||||||
Physics2DServer::get_singleton()->free(shape);
|
Physics2DServer::get_singleton()->free(shape);
|
||||||
|
|
|
@ -47,6 +47,12 @@ public:
|
||||||
void set_custom_solver_bias(real_t p_bias);
|
void set_custom_solver_bias(real_t p_bias);
|
||||||
real_t get_custom_solver_bias() const;
|
real_t get_custom_solver_bias() const;
|
||||||
|
|
||||||
|
bool collide_with_motion(const Matrix32& p_local_xform, const Vector2& p_local_motion, const Ref<Shape2D>& p_shape, const Matrix32& p_shape_xform, const Vector2 &p_p_shape_motion);
|
||||||
|
bool collide(const Matrix32& p_local_xform, const Ref<Shape2D>& p_shape, const Matrix32& p_shape_xform);
|
||||||
|
|
||||||
|
Variant collide_with_motion_and_get_contacts(const Matrix32& p_local_xform, const Vector2& p_local_motion, const Ref<Shape2D>& p_shape, const Matrix32& p_shape_xform, const Vector2 &p_p_shape_motion);
|
||||||
|
Variant collide_and_get_contacts(const Matrix32& p_local_xform, const Ref<Shape2D>& p_shape, const Matrix32& p_shape_xform);
|
||||||
|
|
||||||
virtual RID get_rid() const;
|
virtual RID get_rid() const;
|
||||||
Shape2D();
|
Shape2D();
|
||||||
~Shape2D();
|
~Shape2D();
|
||||||
|
|
|
@ -44,8 +44,10 @@ bool TileSet::_set(const StringName& p_name, const Variant& p_value) {
|
||||||
tile_set_name(id,p_value);
|
tile_set_name(id,p_value);
|
||||||
else if (what=="texture")
|
else if (what=="texture")
|
||||||
tile_set_texture(id,p_value);
|
tile_set_texture(id,p_value);
|
||||||
else if (what=="offset")
|
else if (what=="tex_offset")
|
||||||
tile_set_offset(id,p_value);
|
tile_set_texture_offset(id,p_value);
|
||||||
|
else if (what=="shape_offset")
|
||||||
|
tile_set_shape_offset(id,p_value);
|
||||||
else if (what=="region")
|
else if (what=="region")
|
||||||
tile_set_region(id,p_value);
|
tile_set_region(id,p_value);
|
||||||
else if (what=="shape")
|
else if (what=="shape")
|
||||||
|
@ -75,8 +77,10 @@ bool TileSet::_get(const StringName& p_name,Variant &r_ret) const{
|
||||||
r_ret=tile_get_name(id);
|
r_ret=tile_get_name(id);
|
||||||
else if (what=="texture")
|
else if (what=="texture")
|
||||||
r_ret=tile_get_texture(id);
|
r_ret=tile_get_texture(id);
|
||||||
else if (what=="offset")
|
else if (what=="tex_offset")
|
||||||
r_ret=tile_get_offset(id);
|
r_ret=tile_get_texture_offset(id);
|
||||||
|
else if (what=="shape_offset")
|
||||||
|
r_ret=tile_get_shape_offset(id);
|
||||||
else if (what=="region")
|
else if (what=="region")
|
||||||
r_ret=tile_get_region(id);
|
r_ret=tile_get_region(id);
|
||||||
else if (what=="shape")
|
else if (what=="shape")
|
||||||
|
@ -98,7 +102,8 @@ void TileSet::_get_property_list( List<PropertyInfo> *p_list) const{
|
||||||
String pre = itos(id)+"/";
|
String pre = itos(id)+"/";
|
||||||
p_list->push_back(PropertyInfo(Variant::STRING,pre+"name"));
|
p_list->push_back(PropertyInfo(Variant::STRING,pre+"name"));
|
||||||
p_list->push_back(PropertyInfo(Variant::OBJECT,pre+"texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"));
|
p_list->push_back(PropertyInfo(Variant::OBJECT,pre+"texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"));
|
||||||
p_list->push_back(PropertyInfo(Variant::VECTOR2,pre+"offset"));
|
p_list->push_back(PropertyInfo(Variant::VECTOR2,pre+"tex_offset"));
|
||||||
|
p_list->push_back(PropertyInfo(Variant::VECTOR2,pre+"shape_offset"));
|
||||||
p_list->push_back(PropertyInfo(Variant::RECT2,pre+"region"));
|
p_list->push_back(PropertyInfo(Variant::RECT2,pre+"region"));
|
||||||
p_list->push_back(PropertyInfo(Variant::OBJECT,pre+"shape",PROPERTY_HINT_RESOURCE_TYPE,"Shape2D",PROPERTY_USAGE_EDITOR));
|
p_list->push_back(PropertyInfo(Variant::OBJECT,pre+"shape",PROPERTY_HINT_RESOURCE_TYPE,"Shape2D",PROPERTY_USAGE_EDITOR));
|
||||||
p_list->push_back(PropertyInfo(Variant::ARRAY,pre+"shapes",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR));
|
p_list->push_back(PropertyInfo(Variant::ARRAY,pre+"shapes",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR));
|
||||||
|
@ -129,20 +134,34 @@ Ref<Texture> TileSet::tile_get_texture(int p_id) const {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileSet::tile_set_offset(int p_id,const Vector2 &p_offset) {
|
void TileSet::tile_set_texture_offset(int p_id,const Vector2 &p_offset) {
|
||||||
|
|
||||||
ERR_FAIL_COND(!tile_map.has(p_id));
|
ERR_FAIL_COND(!tile_map.has(p_id));
|
||||||
tile_map[p_id].offset=p_offset;
|
tile_map[p_id].offset=p_offset;
|
||||||
emit_changed();
|
emit_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2 TileSet::tile_get_offset(int p_id) const {
|
Vector2 TileSet::tile_get_texture_offset(int p_id) const {
|
||||||
|
|
||||||
ERR_FAIL_COND_V(!tile_map.has(p_id),Vector2());
|
ERR_FAIL_COND_V(!tile_map.has(p_id),Vector2());
|
||||||
return tile_map[p_id].offset;
|
return tile_map[p_id].offset;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TileSet::tile_set_shape_offset(int p_id,const Vector2 &p_offset) {
|
||||||
|
|
||||||
|
ERR_FAIL_COND(!tile_map.has(p_id));
|
||||||
|
tile_map[p_id].shape_offset=p_offset;
|
||||||
|
emit_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 TileSet::tile_get_shape_offset(int p_id) const {
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(!tile_map.has(p_id),Vector2());
|
||||||
|
return tile_map[p_id].shape_offset;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void TileSet::tile_set_region(int p_id,const Rect2 &p_region) {
|
void TileSet::tile_set_region(int p_id,const Rect2 &p_region) {
|
||||||
|
|
||||||
ERR_FAIL_COND(!tile_map.has(p_id));
|
ERR_FAIL_COND(!tile_map.has(p_id));
|
||||||
|
@ -300,8 +319,10 @@ void TileSet::_bind_methods() {
|
||||||
ObjectTypeDB::bind_method(_MD("tile_get_name","id"),&TileSet::tile_get_name);
|
ObjectTypeDB::bind_method(_MD("tile_get_name","id"),&TileSet::tile_get_name);
|
||||||
ObjectTypeDB::bind_method(_MD("tile_set_texture","id","texture:Texture"),&TileSet::tile_set_texture);
|
ObjectTypeDB::bind_method(_MD("tile_set_texture","id","texture:Texture"),&TileSet::tile_set_texture);
|
||||||
ObjectTypeDB::bind_method(_MD("tile_get_texture:Texture","id"),&TileSet::tile_get_texture);
|
ObjectTypeDB::bind_method(_MD("tile_get_texture:Texture","id"),&TileSet::tile_get_texture);
|
||||||
ObjectTypeDB::bind_method(_MD("tile_set_offset","id","offset"),&TileSet::tile_set_offset);
|
ObjectTypeDB::bind_method(_MD("tile_set_texture_offset","id","texture_offset"),&TileSet::tile_set_texture_offset);
|
||||||
ObjectTypeDB::bind_method(_MD("tile_get_offset","id"),&TileSet::tile_get_offset);
|
ObjectTypeDB::bind_method(_MD("tile_get_texture_offset","id"),&TileSet::tile_get_texture_offset);
|
||||||
|
ObjectTypeDB::bind_method(_MD("tile_set_shape_offset","id","shape_offset"),&TileSet::tile_set_shape_offset);
|
||||||
|
ObjectTypeDB::bind_method(_MD("tile_get_shape_offset","id"),&TileSet::tile_get_shape_offset);
|
||||||
ObjectTypeDB::bind_method(_MD("tile_set_region","id","region"),&TileSet::tile_set_region);
|
ObjectTypeDB::bind_method(_MD("tile_set_region","id","region"),&TileSet::tile_set_region);
|
||||||
ObjectTypeDB::bind_method(_MD("tile_get_region","id"),&TileSet::tile_get_region);
|
ObjectTypeDB::bind_method(_MD("tile_get_region","id"),&TileSet::tile_get_region);
|
||||||
ObjectTypeDB::bind_method(_MD("tile_set_shape","id","shape:Shape2D"),&TileSet::tile_set_shape);
|
ObjectTypeDB::bind_method(_MD("tile_set_shape","id","shape:Shape2D"),&TileSet::tile_set_shape);
|
||||||
|
|
|
@ -42,6 +42,7 @@ class TileSet : public Resource {
|
||||||
String name;
|
String name;
|
||||||
Ref<Texture> texture;
|
Ref<Texture> texture;
|
||||||
Vector2 offset;
|
Vector2 offset;
|
||||||
|
Vector2 shape_offset;
|
||||||
Rect2i region;
|
Rect2i region;
|
||||||
Vector<Ref<Shape2D> > shapes;
|
Vector<Ref<Shape2D> > shapes;
|
||||||
};
|
};
|
||||||
|
@ -71,8 +72,11 @@ public:
|
||||||
void tile_set_texture(int p_id, const Ref<Texture> &p_texture);
|
void tile_set_texture(int p_id, const Ref<Texture> &p_texture);
|
||||||
Ref<Texture> tile_get_texture(int p_id) const;
|
Ref<Texture> tile_get_texture(int p_id) const;
|
||||||
|
|
||||||
void tile_set_offset(int p_id,const Vector2 &p_offset);
|
void tile_set_texture_offset(int p_id,const Vector2 &p_offset);
|
||||||
Vector2 tile_get_offset(int p_id) const;
|
Vector2 tile_get_texture_offset(int p_id) const;
|
||||||
|
|
||||||
|
void tile_set_shape_offset(int p_id,const Vector2 &p_offset);
|
||||||
|
Vector2 tile_get_shape_offset(int p_id) const;
|
||||||
|
|
||||||
void tile_set_region(int p_id,const Rect2 &p_region);
|
void tile_set_region(int p_id,const Rect2 &p_region);
|
||||||
Rect2 tile_get_region(int p_id) const;
|
Rect2 tile_get_region(int p_id) const;
|
||||||
|
|
|
@ -198,7 +198,7 @@ bool BodyPairSW::setup(float p_step) {
|
||||||
|
|
||||||
|
|
||||||
//cannot collide
|
//cannot collide
|
||||||
if (A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode()<=PhysicsServer::BODY_MODE_STATIC_ACTIVE && B->get_mode()<=PhysicsServer::BODY_MODE_STATIC_ACTIVE)) {
|
if (A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC && B->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -84,7 +84,7 @@ void Area2DSW::set_monitor_callback(ObjectID p_id, const StringName& p_method) {
|
||||||
|
|
||||||
void Area2DSW::set_space_override_mode(Physics2DServer::AreaSpaceOverrideMode p_mode) {
|
void Area2DSW::set_space_override_mode(Physics2DServer::AreaSpaceOverrideMode p_mode) {
|
||||||
bool do_override=p_mode!=Physics2DServer::AREA_SPACE_OVERRIDE_DISABLED;
|
bool do_override=p_mode!=Physics2DServer::AREA_SPACE_OVERRIDE_DISABLED;
|
||||||
if (do_override==space_override_mode!=Physics2DServer::AREA_SPACE_OVERRIDE_DISABLED)
|
if (do_override==(space_override_mode!=Physics2DServer::AREA_SPACE_OVERRIDE_DISABLED))
|
||||||
return;
|
return;
|
||||||
_unregister_shapes();
|
_unregister_shapes();
|
||||||
space_override_mode=p_mode;
|
space_override_mode=p_mode;
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
|
|
||||||
bool AreaPair2DSW::setup(float p_step) {
|
bool AreaPair2DSW::setup(float p_step) {
|
||||||
|
|
||||||
bool result = CollisionSolver2DSW::solve_static(body->get_shape(body_shape),body->get_transform() * body->get_shape_transform(body_shape),body->get_shape_inv_transform(body_shape) * body->get_inv_transform(),area->get_shape(area_shape),area->get_transform() * area->get_shape_transform(area_shape),area->get_shape_inv_transform(area_shape) * area->get_inv_transform(),NULL,this);
|
bool result = CollisionSolver2DSW::solve(body->get_shape(body_shape),body->get_transform() * body->get_shape_transform(body_shape),Vector2(),area->get_shape(area_shape),area->get_transform() * area->get_shape_transform(area_shape),Vector2(),NULL,this);
|
||||||
|
|
||||||
if (result!=colliding) {
|
if (result!=colliding) {
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -26,309 +26,321 @@
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
#ifndef BODY_2D_SW_H
|
#ifndef BODY_2D_SW_H
|
||||||
#define BODY_2D_SW_H
|
#define BODY_2D_SW_H
|
||||||
|
|
||||||
#include "collision_object_2d_sw.h"
|
#include "collision_object_2d_sw.h"
|
||||||
#include "vset.h"
|
#include "vset.h"
|
||||||
#include "area_2d_sw.h"
|
#include "area_2d_sw.h"
|
||||||
|
|
||||||
class Constraint2DSW;
|
class Constraint2DSW;
|
||||||
|
|
||||||
|
|
||||||
class Body2DSW : public CollisionObject2DSW {
|
class Body2DSW : public CollisionObject2DSW {
|
||||||
|
|
||||||
|
|
||||||
Physics2DServer::BodyMode mode;
|
Physics2DServer::BodyMode mode;
|
||||||
|
|
||||||
Vector2 biased_linear_velocity;
|
Vector2 biased_linear_velocity;
|
||||||
real_t biased_angular_velocity;
|
real_t biased_angular_velocity;
|
||||||
|
|
||||||
Vector2 linear_velocity;
|
Vector2 linear_velocity;
|
||||||
real_t angular_velocity;
|
real_t angular_velocity;
|
||||||
|
|
||||||
real_t mass;
|
real_t mass;
|
||||||
real_t bounce;
|
real_t bounce;
|
||||||
real_t friction;
|
real_t friction;
|
||||||
|
|
||||||
real_t _inv_mass;
|
real_t _inv_mass;
|
||||||
real_t _inv_inertia;
|
real_t _inv_inertia;
|
||||||
|
|
||||||
Vector2 gravity;
|
Vector2 gravity;
|
||||||
real_t density;
|
real_t density;
|
||||||
|
|
||||||
real_t still_time;
|
real_t still_time;
|
||||||
|
|
||||||
Vector2 applied_force;
|
Vector2 applied_force;
|
||||||
real_t applied_torque;
|
real_t applied_torque;
|
||||||
|
|
||||||
SelfList<Body2DSW> active_list;
|
SelfList<Body2DSW> active_list;
|
||||||
SelfList<Body2DSW> inertia_update_list;
|
SelfList<Body2DSW> inertia_update_list;
|
||||||
SelfList<Body2DSW> direct_state_query_list;
|
SelfList<Body2DSW> direct_state_query_list;
|
||||||
|
|
||||||
VSet<RID> exceptions;
|
VSet<RID> exceptions;
|
||||||
bool omit_force_integration;
|
Physics2DServer::CCDMode continuous_cd_mode;
|
||||||
bool active;
|
bool omit_force_integration;
|
||||||
bool simulated_motion;
|
bool active;
|
||||||
bool continuous_cd;
|
bool can_sleep;
|
||||||
bool can_sleep;
|
void _update_inertia();
|
||||||
void _update_inertia();
|
virtual void _shapes_changed();
|
||||||
virtual void _shapes_changed();
|
Matrix32 new_transform;
|
||||||
|
|
||||||
|
|
||||||
Map<Constraint2DSW*,int> constraint_map;
|
Map<Constraint2DSW*,int> constraint_map;
|
||||||
|
|
||||||
struct AreaCMP {
|
struct AreaCMP {
|
||||||
|
|
||||||
Area2DSW *area;
|
Area2DSW *area;
|
||||||
_FORCE_INLINE_ bool operator<(const AreaCMP& p_cmp) const { return area->get_self() < p_cmp.area->get_self() ; }
|
_FORCE_INLINE_ bool operator<(const AreaCMP& p_cmp) const { return area->get_self() < p_cmp.area->get_self() ; }
|
||||||
_FORCE_INLINE_ AreaCMP() {}
|
_FORCE_INLINE_ AreaCMP() {}
|
||||||
_FORCE_INLINE_ AreaCMP(Area2DSW *p_area) { area=p_area;}
|
_FORCE_INLINE_ AreaCMP(Area2DSW *p_area) { area=p_area;}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
VSet<AreaCMP> areas;
|
VSet<AreaCMP> areas;
|
||||||
|
|
||||||
struct Contact {
|
struct Contact {
|
||||||
|
|
||||||
|
|
||||||
Vector2 local_pos;
|
Vector2 local_pos;
|
||||||
Vector2 local_normal;
|
Vector2 local_normal;
|
||||||
float depth;
|
float depth;
|
||||||
int local_shape;
|
int local_shape;
|
||||||
Vector2 collider_pos;
|
Vector2 collider_pos;
|
||||||
int collider_shape;
|
int collider_shape;
|
||||||
ObjectID collider_instance_id;
|
ObjectID collider_instance_id;
|
||||||
RID collider;
|
RID collider;
|
||||||
Vector2 collider_velocity_at_pos;
|
Vector2 collider_velocity_at_pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
Vector<Contact> contacts; //no contacts by default
|
Vector<Contact> contacts; //no contacts by default
|
||||||
int contact_count;
|
int contact_count;
|
||||||
|
|
||||||
struct ForceIntegrationCallback {
|
struct ForceIntegrationCallback {
|
||||||
|
|
||||||
ObjectID id;
|
ObjectID id;
|
||||||
StringName method;
|
StringName method;
|
||||||
Variant callback_udata;
|
Variant callback_udata;
|
||||||
};
|
};
|
||||||
|
|
||||||
ForceIntegrationCallback *fi_callback;
|
ForceIntegrationCallback *fi_callback;
|
||||||
|
|
||||||
|
|
||||||
uint64_t island_step;
|
uint64_t island_step;
|
||||||
Body2DSW *island_next;
|
Body2DSW *island_next;
|
||||||
Body2DSW *island_list_next;
|
Body2DSW *island_list_next;
|
||||||
|
|
||||||
_FORCE_INLINE_ void _compute_area_gravity(const Area2DSW *p_area);
|
_FORCE_INLINE_ void _compute_area_gravity(const Area2DSW *p_area);
|
||||||
|
|
||||||
friend class Physics2DDirectBodyStateSW; // i give up, too many functions to expose
|
friend class Physics2DDirectBodyStateSW; // i give up, too many functions to expose
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
||||||
void set_force_integration_callback(ObjectID p_id, const StringName& p_method, const Variant &p_udata=Variant());
|
void set_force_integration_callback(ObjectID p_id, const StringName& p_method, const Variant &p_udata=Variant());
|
||||||
|
|
||||||
|
|
||||||
_FORCE_INLINE_ void add_area(Area2DSW *p_area) { areas.insert(AreaCMP(p_area)); }
|
_FORCE_INLINE_ void add_area(Area2DSW *p_area) { areas.insert(AreaCMP(p_area)); }
|
||||||
_FORCE_INLINE_ void remove_area(Area2DSW *p_area) { areas.erase(AreaCMP(p_area)); }
|
_FORCE_INLINE_ void remove_area(Area2DSW *p_area) { areas.erase(AreaCMP(p_area)); }
|
||||||
|
|
||||||
_FORCE_INLINE_ void set_max_contacts_reported(int p_size) { contacts.resize(p_size); contact_count=0; }
|
_FORCE_INLINE_ void set_max_contacts_reported(int p_size) { contacts.resize(p_size); contact_count=0; }
|
||||||
_FORCE_INLINE_ int get_max_contacts_reported() const { return contacts.size(); }
|
_FORCE_INLINE_ int get_max_contacts_reported() const { return contacts.size(); }
|
||||||
|
|
||||||
_FORCE_INLINE_ bool can_report_contacts() const { return !contacts.empty(); }
|
_FORCE_INLINE_ bool can_report_contacts() const { return !contacts.empty(); }
|
||||||
_FORCE_INLINE_ void add_contact(const Vector2& p_local_pos,const Vector2& p_local_normal, float p_depth, int p_local_shape, const Vector2& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector2& p_collider_velocity_at_pos);
|
_FORCE_INLINE_ void add_contact(const Vector2& p_local_pos,const Vector2& p_local_normal, float p_depth, int p_local_shape, const Vector2& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector2& p_collider_velocity_at_pos);
|
||||||
|
|
||||||
|
|
||||||
_FORCE_INLINE_ void add_exception(const RID& p_exception) { exceptions.insert(p_exception);}
|
_FORCE_INLINE_ void add_exception(const RID& p_exception) { exceptions.insert(p_exception);}
|
||||||
_FORCE_INLINE_ void remove_exception(const RID& p_exception) { exceptions.erase(p_exception);}
|
_FORCE_INLINE_ void remove_exception(const RID& p_exception) { exceptions.erase(p_exception);}
|
||||||
_FORCE_INLINE_ bool has_exception(const RID& p_exception) const { return exceptions.has(p_exception);}
|
_FORCE_INLINE_ bool has_exception(const RID& p_exception) const { return exceptions.has(p_exception);}
|
||||||
_FORCE_INLINE_ const VSet<RID>& get_exceptions() const { return exceptions;}
|
_FORCE_INLINE_ const VSet<RID>& get_exceptions() const { return exceptions;}
|
||||||
|
|
||||||
_FORCE_INLINE_ uint64_t get_island_step() const { return island_step; }
|
_FORCE_INLINE_ uint64_t get_island_step() const { return island_step; }
|
||||||
_FORCE_INLINE_ void set_island_step(uint64_t p_step) { island_step=p_step; }
|
_FORCE_INLINE_ void set_island_step(uint64_t p_step) { island_step=p_step; }
|
||||||
|
|
||||||
_FORCE_INLINE_ Body2DSW* get_island_next() const { return island_next; }
|
_FORCE_INLINE_ Body2DSW* get_island_next() const { return island_next; }
|
||||||
_FORCE_INLINE_ void set_island_next(Body2DSW* p_next) { island_next=p_next; }
|
_FORCE_INLINE_ void set_island_next(Body2DSW* p_next) { island_next=p_next; }
|
||||||
|
|
||||||
_FORCE_INLINE_ Body2DSW* get_island_list_next() const { return island_list_next; }
|
_FORCE_INLINE_ Body2DSW* get_island_list_next() const { return island_list_next; }
|
||||||
_FORCE_INLINE_ void set_island_list_next(Body2DSW* p_next) { island_list_next=p_next; }
|
_FORCE_INLINE_ void set_island_list_next(Body2DSW* p_next) { island_list_next=p_next; }
|
||||||
|
|
||||||
_FORCE_INLINE_ void add_constraint(Constraint2DSW* p_constraint, int p_pos) { constraint_map[p_constraint]=p_pos; }
|
_FORCE_INLINE_ void add_constraint(Constraint2DSW* p_constraint, int p_pos) { constraint_map[p_constraint]=p_pos; }
|
||||||
_FORCE_INLINE_ void remove_constraint(Constraint2DSW* p_constraint) { constraint_map.erase(p_constraint); }
|
_FORCE_INLINE_ void remove_constraint(Constraint2DSW* p_constraint) { constraint_map.erase(p_constraint); }
|
||||||
const Map<Constraint2DSW*,int>& get_constraint_map() const { return constraint_map; }
|
const Map<Constraint2DSW*,int>& get_constraint_map() const { return constraint_map; }
|
||||||
|
|
||||||
_FORCE_INLINE_ void set_omit_force_integration(bool p_omit_force_integration) { omit_force_integration=p_omit_force_integration; }
|
_FORCE_INLINE_ void set_omit_force_integration(bool p_omit_force_integration) { omit_force_integration=p_omit_force_integration; }
|
||||||
_FORCE_INLINE_ bool get_omit_force_integration() const { return omit_force_integration; }
|
_FORCE_INLINE_ bool get_omit_force_integration() const { return omit_force_integration; }
|
||||||
|
|
||||||
_FORCE_INLINE_ void set_linear_velocity(const Vector2& p_velocity) {linear_velocity=p_velocity; }
|
_FORCE_INLINE_ void set_linear_velocity(const Vector2& p_velocity) {linear_velocity=p_velocity; }
|
||||||
_FORCE_INLINE_ Vector2 get_linear_velocity() const { return linear_velocity; }
|
_FORCE_INLINE_ Vector2 get_linear_velocity() const { return linear_velocity; }
|
||||||
|
|
||||||
_FORCE_INLINE_ void set_angular_velocity(real_t p_velocity) { angular_velocity=p_velocity; }
|
_FORCE_INLINE_ void set_angular_velocity(real_t p_velocity) { angular_velocity=p_velocity; }
|
||||||
_FORCE_INLINE_ real_t get_angular_velocity() const { return angular_velocity; }
|
_FORCE_INLINE_ real_t get_angular_velocity() const { return angular_velocity; }
|
||||||
|
|
||||||
_FORCE_INLINE_ void set_biased_linear_velocity(const Vector2& p_velocity) {biased_linear_velocity=p_velocity; }
|
_FORCE_INLINE_ void set_biased_linear_velocity(const Vector2& p_velocity) {biased_linear_velocity=p_velocity; }
|
||||||
_FORCE_INLINE_ Vector2 get_biased_linear_velocity() const { return biased_linear_velocity; }
|
_FORCE_INLINE_ Vector2 get_biased_linear_velocity() const { return biased_linear_velocity; }
|
||||||
|
|
||||||
_FORCE_INLINE_ void set_biased_angular_velocity(real_t p_velocity) { biased_angular_velocity=p_velocity; }
|
_FORCE_INLINE_ void set_biased_angular_velocity(real_t p_velocity) { biased_angular_velocity=p_velocity; }
|
||||||
_FORCE_INLINE_ real_t get_biased_angular_velocity() const { return biased_angular_velocity; }
|
_FORCE_INLINE_ real_t get_biased_angular_velocity() const { return biased_angular_velocity; }
|
||||||
|
|
||||||
_FORCE_INLINE_ void apply_impulse(const Vector2& p_pos, const Vector2& p_j) {
|
|
||||||
|
_FORCE_INLINE_ void apply_impulse(const Vector2& p_pos, const Vector2& p_j) {
|
||||||
linear_velocity += p_j * _inv_mass;
|
|
||||||
angular_velocity += _inv_inertia * p_pos.cross(p_j);
|
linear_velocity += p_j * _inv_mass;
|
||||||
}
|
angular_velocity += _inv_inertia * p_pos.cross(p_j);
|
||||||
|
}
|
||||||
_FORCE_INLINE_ void apply_bias_impulse(const Vector2& p_pos, const Vector2& p_j) {
|
|
||||||
|
_FORCE_INLINE_ void apply_bias_impulse(const Vector2& p_pos, const Vector2& p_j) {
|
||||||
biased_linear_velocity += p_j * _inv_mass;
|
|
||||||
biased_angular_velocity += _inv_inertia * p_pos.cross(p_j);
|
biased_linear_velocity += p_j * _inv_mass;
|
||||||
}
|
biased_angular_velocity += _inv_inertia * p_pos.cross(p_j);
|
||||||
|
}
|
||||||
void set_active(bool p_active);
|
|
||||||
_FORCE_INLINE_ bool is_active() const { return active; }
|
void set_active(bool p_active);
|
||||||
|
_FORCE_INLINE_ bool is_active() const { return active; }
|
||||||
void set_param(Physics2DServer::BodyParameter p_param, float);
|
|
||||||
float get_param(Physics2DServer::BodyParameter p_param) const;
|
void set_param(Physics2DServer::BodyParameter p_param, float);
|
||||||
|
float get_param(Physics2DServer::BodyParameter p_param) const;
|
||||||
void set_mode(Physics2DServer::BodyMode p_mode);
|
|
||||||
Physics2DServer::BodyMode get_mode() const;
|
void set_mode(Physics2DServer::BodyMode p_mode);
|
||||||
|
Physics2DServer::BodyMode get_mode() const;
|
||||||
void set_state(Physics2DServer::BodyState p_state, const Variant& p_variant);
|
|
||||||
Variant get_state(Physics2DServer::BodyState p_state) const;
|
void set_state(Physics2DServer::BodyState p_state, const Variant& p_variant);
|
||||||
|
Variant get_state(Physics2DServer::BodyState p_state) const;
|
||||||
void set_applied_force(const Vector2& p_force) { applied_force=p_force; }
|
|
||||||
Vector2 get_applied_force() const { return applied_force; }
|
void set_applied_force(const Vector2& p_force) { applied_force=p_force; }
|
||||||
|
Vector2 get_applied_force() const { return applied_force; }
|
||||||
void set_applied_torque(real_t p_torque) { applied_torque=p_torque; }
|
|
||||||
real_t get_applied_torque() const { return applied_torque; }
|
void set_applied_torque(real_t p_torque) { applied_torque=p_torque; }
|
||||||
|
real_t get_applied_torque() const { return applied_torque; }
|
||||||
_FORCE_INLINE_ void set_continuous_collision_detection(bool p_enable) { continuous_cd=p_enable; }
|
|
||||||
_FORCE_INLINE_ bool is_continuous_collision_detection_enabled() const { return continuous_cd; }
|
|
||||||
|
_FORCE_INLINE_ void set_continuous_collision_detection_mode(Physics2DServer::CCDMode p_mode) { continuous_cd_mode=p_mode; }
|
||||||
void set_space(Space2DSW *p_space);
|
_FORCE_INLINE_ Physics2DServer::CCDMode get_continuous_collision_detection_mode() const { return continuous_cd_mode; }
|
||||||
|
|
||||||
void update_inertias();
|
void set_space(Space2DSW *p_space);
|
||||||
|
|
||||||
_FORCE_INLINE_ real_t get_inv_mass() const { return _inv_mass; }
|
void update_inertias();
|
||||||
_FORCE_INLINE_ real_t get_inv_inertia() const { return _inv_inertia; }
|
|
||||||
_FORCE_INLINE_ real_t get_friction() const { return friction; }
|
_FORCE_INLINE_ real_t get_inv_mass() const { return _inv_mass; }
|
||||||
_FORCE_INLINE_ Vector2 get_gravity() const { return gravity; }
|
_FORCE_INLINE_ real_t get_inv_inertia() const { return _inv_inertia; }
|
||||||
_FORCE_INLINE_ real_t get_density() const { return density; }
|
_FORCE_INLINE_ real_t get_friction() const { return friction; }
|
||||||
|
_FORCE_INLINE_ Vector2 get_gravity() const { return gravity; }
|
||||||
void integrate_forces(real_t p_step);
|
_FORCE_INLINE_ real_t get_density() const { return density; }
|
||||||
void integrate_velocities(real_t p_step);
|
_FORCE_INLINE_ real_t get_bounce() const { return bounce; }
|
||||||
|
|
||||||
void simulate_motion(const Matrix32& p_xform,real_t p_step);
|
void integrate_forces(real_t p_step);
|
||||||
void call_queries();
|
void integrate_velocities(real_t p_step);
|
||||||
void wakeup_neighbours();
|
|
||||||
|
_FORCE_INLINE_ Vector2 get_motion() const {
|
||||||
bool sleep_test(real_t p_step);
|
|
||||||
|
if (mode>Physics2DServer::BODY_MODE_KINEMATIC) {
|
||||||
Body2DSW();
|
return new_transform.get_origin() - get_transform().get_origin();
|
||||||
~Body2DSW();
|
} else if (mode==Physics2DServer::BODY_MODE_KINEMATIC) {
|
||||||
|
return get_transform().get_origin() -new_transform.get_origin(); //kinematic simulates forward
|
||||||
};
|
}
|
||||||
|
return Vector2();
|
||||||
|
}
|
||||||
//add contact inline
|
|
||||||
|
void call_queries();
|
||||||
void Body2DSW::add_contact(const Vector2& p_local_pos,const Vector2& p_local_normal, float p_depth, int p_local_shape, const Vector2& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector2& p_collider_velocity_at_pos) {
|
void wakeup_neighbours();
|
||||||
|
|
||||||
int c_max=contacts.size();
|
bool sleep_test(real_t p_step);
|
||||||
|
|
||||||
if (c_max==0)
|
Body2DSW();
|
||||||
return;
|
~Body2DSW();
|
||||||
|
|
||||||
Contact *c = &contacts[0];
|
};
|
||||||
|
|
||||||
|
|
||||||
int idx=-1;
|
//add contact inline
|
||||||
|
|
||||||
if (contact_count<c_max) {
|
void Body2DSW::add_contact(const Vector2& p_local_pos,const Vector2& p_local_normal, float p_depth, int p_local_shape, const Vector2& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector2& p_collider_velocity_at_pos) {
|
||||||
idx=contact_count++;
|
|
||||||
} else {
|
int c_max=contacts.size();
|
||||||
|
|
||||||
float least_depth=1e20;
|
if (c_max==0)
|
||||||
int least_deep=-1;
|
return;
|
||||||
for(int i=0;i<c_max;i++) {
|
|
||||||
|
Contact *c = &contacts[0];
|
||||||
if (i==0 || c[i].depth<least_depth) {
|
|
||||||
least_deep=i;
|
|
||||||
least_depth=c[i].depth;
|
int idx=-1;
|
||||||
}
|
|
||||||
}
|
if (contact_count<c_max) {
|
||||||
|
idx=contact_count++;
|
||||||
if (least_deep>=0 && least_depth<p_depth) {
|
} else {
|
||||||
|
|
||||||
idx=least_deep;
|
float least_depth=1e20;
|
||||||
}
|
int least_deep=-1;
|
||||||
if (idx==-1)
|
for(int i=0;i<c_max;i++) {
|
||||||
return; //none least deepe than this
|
|
||||||
}
|
if (i==0 || c[i].depth<least_depth) {
|
||||||
|
least_deep=i;
|
||||||
c[idx].local_pos=p_local_pos;
|
least_depth=c[i].depth;
|
||||||
c[idx].local_normal=p_local_normal;
|
}
|
||||||
c[idx].depth=p_depth;
|
}
|
||||||
c[idx].local_shape=p_local_shape;
|
|
||||||
c[idx].collider_pos=p_collider_pos;
|
if (least_deep>=0 && least_depth<p_depth) {
|
||||||
c[idx].collider_shape=p_collider_shape;
|
|
||||||
c[idx].collider_instance_id=p_collider_instance_id;
|
idx=least_deep;
|
||||||
c[idx].collider=p_collider;
|
}
|
||||||
c[idx].collider_velocity_at_pos=p_collider_velocity_at_pos;
|
if (idx==-1)
|
||||||
|
return; //none least deepe than this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c[idx].local_pos=p_local_pos;
|
||||||
class Physics2DDirectBodyStateSW : public Physics2DDirectBodyState {
|
c[idx].local_normal=p_local_normal;
|
||||||
|
c[idx].depth=p_depth;
|
||||||
OBJ_TYPE( Physics2DDirectBodyStateSW, Physics2DDirectBodyState );
|
c[idx].local_shape=p_local_shape;
|
||||||
|
c[idx].collider_pos=p_collider_pos;
|
||||||
public:
|
c[idx].collider_shape=p_collider_shape;
|
||||||
|
c[idx].collider_instance_id=p_collider_instance_id;
|
||||||
static Physics2DDirectBodyStateSW *singleton;
|
c[idx].collider=p_collider;
|
||||||
Body2DSW *body;
|
c[idx].collider_velocity_at_pos=p_collider_velocity_at_pos;
|
||||||
real_t step;
|
|
||||||
|
}
|
||||||
virtual Vector2 get_total_gravity() const { return body->get_gravity(); } // get gravity vector working on this body space/area
|
|
||||||
virtual float get_total_density() const { return body->get_density(); } // get density of this body space/area
|
|
||||||
|
class Physics2DDirectBodyStateSW : public Physics2DDirectBodyState {
|
||||||
virtual float get_inverse_mass() const { return body->get_inv_mass(); } // get the mass
|
|
||||||
virtual real_t get_inverse_inertia() const { return body->get_inv_inertia(); } // get density of this body space
|
OBJ_TYPE( Physics2DDirectBodyStateSW, Physics2DDirectBodyState );
|
||||||
|
|
||||||
virtual void set_linear_velocity(const Vector2& p_velocity) { body->set_linear_velocity(p_velocity); }
|
public:
|
||||||
virtual Vector2 get_linear_velocity() const { return body->get_linear_velocity(); }
|
|
||||||
|
static Physics2DDirectBodyStateSW *singleton;
|
||||||
virtual void set_angular_velocity(real_t p_velocity) { body->set_angular_velocity(p_velocity); }
|
Body2DSW *body;
|
||||||
virtual real_t get_angular_velocity() const { return body->get_angular_velocity(); }
|
real_t step;
|
||||||
|
|
||||||
virtual void set_transform(const Matrix32& p_transform) { body->set_state(Physics2DServer::BODY_STATE_TRANSFORM,p_transform); }
|
virtual Vector2 get_total_gravity() const { return body->get_gravity(); } // get gravity vector working on this body space/area
|
||||||
virtual Matrix32 get_transform() const { return body->get_transform(); }
|
virtual float get_total_density() const { return body->get_density(); } // get density of this body space/area
|
||||||
|
|
||||||
virtual void set_sleep_state(bool p_enable) { body->set_active(!p_enable); }
|
virtual float get_inverse_mass() const { return body->get_inv_mass(); } // get the mass
|
||||||
virtual bool is_sleeping() const { return !body->is_active(); }
|
virtual real_t get_inverse_inertia() const { return body->get_inv_inertia(); } // get density of this body space
|
||||||
|
|
||||||
virtual int get_contact_count() const { return body->contact_count; }
|
virtual void set_linear_velocity(const Vector2& p_velocity) { body->set_linear_velocity(p_velocity); }
|
||||||
|
virtual Vector2 get_linear_velocity() const { return body->get_linear_velocity(); }
|
||||||
virtual Vector2 get_contact_local_pos(int p_contact_idx) const {
|
|
||||||
ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Vector2());
|
virtual void set_angular_velocity(real_t p_velocity) { body->set_angular_velocity(p_velocity); }
|
||||||
return body->contacts[p_contact_idx].local_pos;
|
virtual real_t get_angular_velocity() const { return body->get_angular_velocity(); }
|
||||||
}
|
|
||||||
virtual Vector2 get_contact_local_normal(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Vector2()); return body->contacts[p_contact_idx].local_normal; }
|
virtual void set_transform(const Matrix32& p_transform) { body->set_state(Physics2DServer::BODY_STATE_TRANSFORM,p_transform); }
|
||||||
virtual int get_contact_local_shape(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,-1); return body->contacts[p_contact_idx].local_shape; }
|
virtual Matrix32 get_transform() const { return body->get_transform(); }
|
||||||
|
|
||||||
virtual RID get_contact_collider(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,RID()); return body->contacts[p_contact_idx].collider; }
|
virtual void set_sleep_state(bool p_enable) { body->set_active(!p_enable); }
|
||||||
virtual Vector2 get_contact_collider_pos(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Vector2()); return body->contacts[p_contact_idx].collider_pos; }
|
virtual bool is_sleeping() const { return !body->is_active(); }
|
||||||
virtual ObjectID get_contact_collider_id(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,0); return body->contacts[p_contact_idx].collider_instance_id; }
|
|
||||||
virtual int get_contact_collider_shape(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,0); return body->contacts[p_contact_idx].collider_shape; }
|
virtual int get_contact_count() const { return body->contact_count; }
|
||||||
virtual Vector2 get_contact_collider_velocity_at_pos(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Vector2()); return body->contacts[p_contact_idx].collider_velocity_at_pos; }
|
|
||||||
|
virtual Vector2 get_contact_local_pos(int p_contact_idx) const {
|
||||||
virtual Physics2DDirectSpaceState* get_space_state();
|
ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Vector2());
|
||||||
|
return body->contacts[p_contact_idx].local_pos;
|
||||||
|
}
|
||||||
virtual real_t get_step() const { return step; }
|
virtual Vector2 get_contact_local_normal(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Vector2()); return body->contacts[p_contact_idx].local_normal; }
|
||||||
Physics2DDirectBodyStateSW() { singleton=this; body=NULL; }
|
virtual int get_contact_local_shape(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,-1); return body->contacts[p_contact_idx].local_shape; }
|
||||||
};
|
|
||||||
|
virtual RID get_contact_collider(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,RID()); return body->contacts[p_contact_idx].collider; }
|
||||||
|
virtual Vector2 get_contact_collider_pos(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Vector2()); return body->contacts[p_contact_idx].collider_pos; }
|
||||||
#endif // BODY_2D_SW_H
|
virtual ObjectID get_contact_collider_id(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,0); return body->contacts[p_contact_idx].collider_instance_id; }
|
||||||
|
virtual int get_contact_collider_shape(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,0); return body->contacts[p_contact_idx].collider_shape; }
|
||||||
|
virtual Vector2 get_contact_collider_velocity_at_pos(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx,body->contact_count,Vector2()); return body->contacts[p_contact_idx].collider_velocity_at_pos; }
|
||||||
|
|
||||||
|
virtual Physics2DDirectSpaceState* get_space_state();
|
||||||
|
|
||||||
|
|
||||||
|
virtual real_t get_step() const { return step; }
|
||||||
|
Physics2DDirectBodyStateSW() { singleton=this; body=NULL; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // BODY_2D_SW_H
|
||||||
|
|
|
@ -46,7 +46,6 @@ void BodyPair2DSW::_contact_added_callback(const Vector2& p_point_A,const Vector
|
||||||
|
|
||||||
// check if we already have the contact
|
// check if we already have the contact
|
||||||
|
|
||||||
|
|
||||||
Vector2 local_A = A->get_inv_transform().basis_xform(p_point_A);
|
Vector2 local_A = A->get_inv_transform().basis_xform(p_point_A);
|
||||||
Vector2 local_B = B->get_inv_transform().basis_xform(p_point_B-offset_B);
|
Vector2 local_B = B->get_inv_transform().basis_xform(p_point_B-offset_B);
|
||||||
|
|
||||||
|
@ -61,6 +60,7 @@ void BodyPair2DSW::_contact_added_callback(const Vector2& p_point_A,const Vector
|
||||||
contact.acc_tangent_impulse=0;
|
contact.acc_tangent_impulse=0;
|
||||||
contact.local_A=local_A;
|
contact.local_A=local_A;
|
||||||
contact.local_B=local_B;
|
contact.local_B=local_B;
|
||||||
|
contact.reused=true;
|
||||||
contact.normal=(p_point_A-p_point_B).normalized();
|
contact.normal=(p_point_A-p_point_B).normalized();
|
||||||
|
|
||||||
// attempt to determine if the contact will be reused
|
// attempt to determine if the contact will be reused
|
||||||
|
@ -77,7 +77,7 @@ void BodyPair2DSW::_contact_added_callback(const Vector2& p_point_A,const Vector
|
||||||
contact.acc_normal_impulse=c.acc_normal_impulse;
|
contact.acc_normal_impulse=c.acc_normal_impulse;
|
||||||
contact.acc_tangent_impulse=c.acc_tangent_impulse;
|
contact.acc_tangent_impulse=c.acc_tangent_impulse;
|
||||||
contact.acc_bias_impulse=c.acc_bias_impulse;
|
contact.acc_bias_impulse=c.acc_bias_impulse;
|
||||||
new_index=i;
|
new_index=i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,12 +139,26 @@ void BodyPair2DSW::_validate_contacts() {
|
||||||
|
|
||||||
Contact& c = contacts[i];
|
Contact& c = contacts[i];
|
||||||
|
|
||||||
Vector2 global_A = A->get_transform().basis_xform(c.local_A);
|
bool erase=false;
|
||||||
Vector2 global_B = B->get_transform().basis_xform(c.local_B)+offset_B;
|
if (c.reused==false) {
|
||||||
Vector2 axis = global_A - global_B;
|
//was left behind in previous frame
|
||||||
float depth = axis.dot( c.normal );
|
erase=true;
|
||||||
|
} else {
|
||||||
|
c.reused=false;
|
||||||
|
|
||||||
if (depth < -max_separation || (global_B + c.normal * depth - global_A).length_squared() > max_separation2) {
|
Vector2 global_A = A->get_transform().basis_xform(c.local_A);
|
||||||
|
Vector2 global_B = B->get_transform().basis_xform(c.local_B)+offset_B;
|
||||||
|
Vector2 axis = global_A - global_B;
|
||||||
|
float depth = axis.dot( c.normal );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (depth < -max_separation || (global_B + c.normal * depth - global_A).length_squared() > max_separation2) {
|
||||||
|
erase=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (erase) {
|
||||||
// contact no longer needed, remove
|
// contact no longer needed, remove
|
||||||
|
|
||||||
|
|
||||||
|
@ -161,7 +175,9 @@ void BodyPair2DSW::_validate_contacts() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool BodyPair2DSW::_test_ccd(float p_step,Body2DSW *p_A, int p_shape_A,const Matrix32& p_xform_A,const Matrix32& p_xform_inv_A,Body2DSW *p_B, int p_shape_B,const Matrix32& p_xform_B,const Matrix32& p_xform_inv_B,bool p_swap_result) {
|
bool BodyPair2DSW::_test_ccd(float p_step,Body2DSW *p_A, int p_shape_A,const Matrix32& p_xform_A,Body2DSW *p_B, int p_shape_B,const Matrix32& p_xform_B,bool p_swap_result) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Vector2 motion = p_A->get_linear_velocity()*p_step;
|
Vector2 motion = p_A->get_linear_velocity()*p_step;
|
||||||
real_t mlen = motion.length();
|
real_t mlen = motion.length();
|
||||||
|
@ -172,18 +188,24 @@ bool BodyPair2DSW::_test_ccd(float p_step,Body2DSW *p_A, int p_shape_A,const Mat
|
||||||
|
|
||||||
real_t min,max;
|
real_t min,max;
|
||||||
p_A->get_shape(p_shape_A)->project_rangev(mnormal,p_xform_A,min,max);
|
p_A->get_shape(p_shape_A)->project_rangev(mnormal,p_xform_A,min,max);
|
||||||
if (mlen < (max-min)*0.3) //did it move enough in this direction to even attempt raycast? let's say it should move more than 1/3 the size of the object in that axis
|
bool fast_object = mlen > (max-min)*0.3; //going too fast in that direction
|
||||||
|
|
||||||
|
if (fast_object) { //did it move enough in this direction to even attempt raycast? let's say it should move more than 1/3 the size of the object in that axis
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//cast a segment from support in motion normal, in the same direction of motion by motion length
|
//cast a segment from support in motion normal, in the same direction of motion by motion length
|
||||||
|
//support is the worst case collision point, so real collision happened before
|
||||||
int a;
|
int a;
|
||||||
Vector2 s[2];
|
Vector2 s[2];
|
||||||
p_A->get_shape(p_shape_A)->get_supports(p_xform_A.basis_xform(mnormal).normalized(),s,a);
|
p_A->get_shape(p_shape_A)->get_supports(p_xform_A.basis_xform(mnormal).normalized(),s,a);
|
||||||
Vector2 from = p_xform_A.xform(s[0]);
|
Vector2 from = p_xform_A.xform(s[0]);
|
||||||
Vector2 to = from + motion;
|
Vector2 to = from + motion;
|
||||||
|
|
||||||
Vector2 local_from = p_xform_inv_B.xform(from);
|
Matrix32 from_inv = p_xform_B.affine_inverse();
|
||||||
Vector2 local_to = p_xform_inv_B.xform(to);
|
|
||||||
|
Vector2 local_from = from_inv.xform(from-mnormal*mlen*0.1); //start from a little inside the bounding box
|
||||||
|
Vector2 local_to = from_inv.xform(to);
|
||||||
|
|
||||||
Vector2 rpos,rnorm;
|
Vector2 rpos,rnorm;
|
||||||
if (!p_B->get_shape(p_shape_B)->intersect_segment(local_from,local_to,rpos,rnorm))
|
if (!p_B->get_shape(p_shape_B)->intersect_segment(local_from,local_to,rpos,rnorm))
|
||||||
|
@ -191,8 +213,11 @@ bool BodyPair2DSW::_test_ccd(float p_step,Body2DSW *p_A, int p_shape_A,const Mat
|
||||||
|
|
||||||
//ray hit something
|
//ray hit something
|
||||||
|
|
||||||
|
|
||||||
|
Vector2 hitpos = p_xform_B.xform(rpos);
|
||||||
|
|
||||||
Vector2 contact_A = to;
|
Vector2 contact_A = to;
|
||||||
Vector2 contact_B = p_xform_B.xform(rpos);
|
Vector2 contact_B = hitpos;
|
||||||
|
|
||||||
//create a contact
|
//create a contact
|
||||||
|
|
||||||
|
@ -208,41 +233,50 @@ bool BodyPair2DSW::_test_ccd(float p_step,Body2DSW *p_A, int p_shape_A,const Mat
|
||||||
bool BodyPair2DSW::setup(float p_step) {
|
bool BodyPair2DSW::setup(float p_step) {
|
||||||
|
|
||||||
|
|
||||||
|
//cannot collide
|
||||||
|
if (A->is_shape_set_as_trigger(shape_A) || B->is_shape_set_as_trigger(shape_B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode()<=Physics2DServer::BODY_MODE_KINEMATIC && B->get_mode()<=Physics2DServer::BODY_MODE_KINEMATIC)) {
|
||||||
|
collided=false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//use local A coordinates to avoid numerical issues on collision detection
|
//use local A coordinates to avoid numerical issues on collision detection
|
||||||
offset_B = B->get_transform().get_origin() - A->get_transform().get_origin();
|
offset_B = B->get_transform().get_origin() - A->get_transform().get_origin();
|
||||||
|
|
||||||
_validate_contacts();
|
_validate_contacts();
|
||||||
|
|
||||||
//cannot collide
|
|
||||||
if (A->is_shape_set_as_trigger(shape_A) || B->is_shape_set_as_trigger(shape_B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode()<=Physics2DServer::BODY_MODE_STATIC_ACTIVE && B->get_mode()<=Physics2DServer::BODY_MODE_STATIC_ACTIVE)) {
|
|
||||||
collided=false;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Vector2 offset_A = A->get_transform().get_origin();
|
Vector2 offset_A = A->get_transform().get_origin();
|
||||||
Matrix32 xform_Au = A->get_transform().untranslated();
|
Matrix32 xform_Au = A->get_transform().untranslated();
|
||||||
Matrix32 xform_A = xform_Au * A->get_shape_transform(shape_A);
|
Matrix32 xform_A = xform_Au * A->get_shape_transform(shape_A);
|
||||||
Matrix32 xform_inv_A = xform_A.affine_inverse();
|
|
||||||
|
|
||||||
Matrix32 xform_Bu = B->get_transform();
|
Matrix32 xform_Bu = B->get_transform();
|
||||||
xform_Bu.elements[2]-=A->get_transform().get_origin();
|
xform_Bu.elements[2]-=A->get_transform().get_origin();
|
||||||
Matrix32 xform_B = xform_Bu * B->get_shape_transform(shape_B);
|
Matrix32 xform_B = xform_Bu * B->get_shape_transform(shape_B);
|
||||||
Matrix32 xform_inv_B = xform_B.affine_inverse();
|
|
||||||
|
|
||||||
Shape2DSW *shape_A_ptr=A->get_shape(shape_A);
|
Shape2DSW *shape_A_ptr=A->get_shape(shape_A);
|
||||||
Shape2DSW *shape_B_ptr=B->get_shape(shape_B);
|
Shape2DSW *shape_B_ptr=B->get_shape(shape_B);
|
||||||
|
|
||||||
collided = CollisionSolver2DSW::solve_static(shape_A_ptr,xform_A,xform_inv_A,shape_B_ptr,xform_B,xform_inv_B,_add_contact,this,&sep_axis);
|
Vector2 motion_A,motion_B;
|
||||||
|
|
||||||
|
if (A->get_continuous_collision_detection_mode()==Physics2DServer::CCD_MODE_CAST_SHAPE) {
|
||||||
|
motion_A=A->get_motion();
|
||||||
|
}
|
||||||
|
if (B->get_continuous_collision_detection_mode()==Physics2DServer::CCD_MODE_CAST_SHAPE) {
|
||||||
|
motion_B=B->get_motion();
|
||||||
|
}
|
||||||
|
//faster to set than to check..
|
||||||
|
|
||||||
|
collided = CollisionSolver2DSW::solve(shape_A_ptr,xform_A,motion_A,shape_B_ptr,xform_B,motion_B,_add_contact,this,&sep_axis);
|
||||||
if (!collided) {
|
if (!collided) {
|
||||||
|
|
||||||
//test ccd (currently just a raycast)
|
//test ccd (currently just a raycast)
|
||||||
if (A->is_continuous_collision_detection_enabled() && A->get_type()>Physics2DServer::BODY_MODE_STATIC_ACTIVE) {
|
|
||||||
if (_test_ccd(p_step,A,shape_A,xform_A,xform_inv_A,B,shape_B,xform_B,xform_inv_B))
|
if (A->get_continuous_collision_detection_mode()==Physics2DServer::CCD_MODE_CAST_RAY && A->get_mode()>Physics2DServer::BODY_MODE_KINEMATIC) {
|
||||||
|
if (_test_ccd(p_step,A,shape_A,xform_A,B,shape_B,xform_B))
|
||||||
collided=true;
|
collided=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (B->is_continuous_collision_detection_enabled() && B->get_type()>Physics2DServer::BODY_MODE_STATIC_ACTIVE) {
|
if (B->get_continuous_collision_detection_mode()==Physics2DServer::CCD_MODE_CAST_RAY && B->get_mode()>Physics2DServer::BODY_MODE_KINEMATIC) {
|
||||||
if (_test_ccd(p_step,B,shape_B,xform_B,xform_inv_B,A,shape_A,xform_A,xform_inv_A,true))
|
if (_test_ccd(p_step,B,shape_B,xform_B,A,shape_A,xform_A,true))
|
||||||
collided=true;
|
collided=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,8 +285,6 @@ bool BodyPair2DSW::setup(float p_step) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
real_t max_penetration = space->get_contact_max_allowed_penetration();
|
real_t max_penetration = space->get_contact_max_allowed_penetration();
|
||||||
|
|
||||||
float bias = 0.3f;
|
float bias = 0.3f;
|
||||||
|
@ -280,7 +312,7 @@ bool BodyPair2DSW::setup(float p_step) {
|
||||||
|
|
||||||
real_t depth = c.normal.dot(global_A - global_B);
|
real_t depth = c.normal.dot(global_A - global_B);
|
||||||
|
|
||||||
if (depth<=0) {
|
if (depth<=0 || !c.reused) {
|
||||||
c.active=false;
|
c.active=false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -311,7 +343,6 @@ bool BodyPair2DSW::setup(float p_step) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Precompute normal mass, tangent mass, and bias.
|
// Precompute normal mass, tangent mass, and bias.
|
||||||
real_t rnA = c.rA.dot(c.normal);
|
real_t rnA = c.rA.dot(c.normal);
|
||||||
real_t rnB = c.rB.dot(c.normal);
|
real_t rnB = c.rB.dot(c.normal);
|
||||||
|
@ -373,6 +404,7 @@ void BodyPair2DSW::solve(float p_step) {
|
||||||
Vector2 crbB( -B->get_biased_angular_velocity() * c.rB.y, B->get_biased_angular_velocity() * c.rB.x );
|
Vector2 crbB( -B->get_biased_angular_velocity() * c.rB.y, B->get_biased_angular_velocity() * c.rB.x );
|
||||||
Vector2 dbv = B->get_biased_linear_velocity() + crbB - A->get_biased_linear_velocity() - crbA;
|
Vector2 dbv = B->get_biased_linear_velocity() + crbB - A->get_biased_linear_velocity() - crbA;
|
||||||
|
|
||||||
|
|
||||||
real_t vn = dv.dot(c.normal);
|
real_t vn = dv.dot(c.normal);
|
||||||
real_t vbn = dbv.dot(c.normal);
|
real_t vbn = dbv.dot(c.normal);
|
||||||
Vector2 tangent = c.normal.tangent();
|
Vector2 tangent = c.normal.tangent();
|
||||||
|
@ -388,7 +420,7 @@ void BodyPair2DSW::solve(float p_step) {
|
||||||
A->apply_bias_impulse(c.rA,-jb);
|
A->apply_bias_impulse(c.rA,-jb);
|
||||||
B->apply_bias_impulse(c.rB, jb);
|
B->apply_bias_impulse(c.rB, jb);
|
||||||
|
|
||||||
real_t bounce=0;
|
real_t bounce=MAX(A->get_bounce(),B->get_bounce());
|
||||||
real_t jn = -(bounce + vn)*c.mass_normal;
|
real_t jn = -(bounce + vn)*c.mass_normal;
|
||||||
real_t jnOld = c.acc_normal_impulse;
|
real_t jnOld = c.acc_normal_impulse;
|
||||||
c.acc_normal_impulse = MAX(jnOld + jn, 0.0f);
|
c.acc_normal_impulse = MAX(jnOld + jn, 0.0f);
|
||||||
|
@ -403,7 +435,6 @@ void BodyPair2DSW::solve(float p_step) {
|
||||||
|
|
||||||
Vector2 j =c.normal * (c.acc_normal_impulse - jnOld) + tangent * ( c.acc_tangent_impulse - jtOld );
|
Vector2 j =c.normal * (c.acc_normal_impulse - jnOld) + tangent * ( c.acc_tangent_impulse - jtOld );
|
||||||
|
|
||||||
|
|
||||||
A->apply_impulse(c.rA,-j);
|
A->apply_impulse(c.rA,-j);
|
||||||
B->apply_impulse(c.rB, j);
|
B->apply_impulse(c.rB, j);
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,7 @@ class BodyPair2DSW : public Constraint2DSW {
|
||||||
real_t depth;
|
real_t depth;
|
||||||
bool active;
|
bool active;
|
||||||
Vector2 rA,rB;
|
Vector2 rA,rB;
|
||||||
|
bool reused;
|
||||||
};
|
};
|
||||||
|
|
||||||
Vector2 offset_B; //use local A coordinates to avoid numerical issues on collision detection
|
Vector2 offset_B; //use local A coordinates to avoid numerical issues on collision detection
|
||||||
|
@ -76,7 +77,7 @@ class BodyPair2DSW : public Constraint2DSW {
|
||||||
int cc;
|
int cc;
|
||||||
|
|
||||||
|
|
||||||
bool _test_ccd(float p_step,Body2DSW *p_A, int p_shape_A,const Matrix32& p_xform_A,const Matrix32& p_xform_inv_A,Body2DSW *p_B, int p_shape_B,const Matrix32& p_xform_B,const Matrix32& p_xform_inv_B,bool p_swap_result=false);
|
bool _test_ccd(float p_step,Body2DSW *p_A, int p_shape_A,const Matrix32& p_xform_A,Body2DSW *p_B, int p_shape_B,const Matrix32& p_xform_B,bool p_swap_result=false);
|
||||||
void _validate_contacts();
|
void _validate_contacts();
|
||||||
static void _add_contact(const Vector2& p_point_A,const Vector2& p_point_B,void *p_self);
|
static void _add_contact(const Vector2& p_point_A,const Vector2& p_point_B,void *p_self);
|
||||||
_FORCE_INLINE_ void _contact_added_callback(const Vector2& p_point_A,const Vector2& p_point_B);
|
_FORCE_INLINE_ void _contact_added_callback(const Vector2& p_point_A,const Vector2& p_point_B);
|
||||||
|
|
|
@ -378,7 +378,8 @@ int BroadPhase2DHashGrid::get_subindex(ID p_id) const {
|
||||||
return E->get().subindex;
|
return E->get().subindex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BroadPhase2DHashGrid::_cull(const Point2i p_cell,CollisionObject2DSW** p_results,int p_max_results,int *p_result_indices,int &index) {
|
template<bool use_aabb,bool use_segment>
|
||||||
|
void BroadPhase2DHashGrid::_cull(const Point2i p_cell,const Rect2& p_aabb,const Point2& p_from, const Point2& p_to,CollisionObject2DSW** p_results,int p_max_results,int *p_result_indices,int &index) {
|
||||||
|
|
||||||
|
|
||||||
PosKey pk;
|
PosKey pk;
|
||||||
|
@ -411,10 +412,18 @@ void BroadPhase2DHashGrid::_cull(const Point2i p_cell,CollisionObject2DSW** p_re
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
E->key()->pass=pass;
|
E->key()->pass=pass;
|
||||||
|
|
||||||
|
if (use_aabb && !p_aabb.intersects(E->key()->aabb))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (use_segment && !E->key()->aabb.intersects_segment(p_from,p_to))
|
||||||
|
continue;
|
||||||
|
|
||||||
p_results[index]=E->key()->owner;
|
p_results[index]=E->key()->owner;
|
||||||
p_result_indices[index]=E->key()->subindex;
|
p_result_indices[index]=E->key()->subindex;
|
||||||
index++;
|
index++;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Map<Element*,RC>::Element *E=pb->static_object_set.front();E;E=E->next()) {
|
for(Map<Element*,RC>::Element *E=pb->static_object_set.front();E;E=E->next()) {
|
||||||
|
@ -425,6 +434,12 @@ void BroadPhase2DHashGrid::_cull(const Point2i p_cell,CollisionObject2DSW** p_re
|
||||||
if (E->key()->pass==pass)
|
if (E->key()->pass==pass)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (use_aabb && !p_aabb.intersects(E->key()->aabb))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (use_segment && !E->key()->aabb.intersects_segment(p_from,p_to))
|
||||||
|
continue;
|
||||||
|
|
||||||
E->key()->pass=pass;
|
E->key()->pass=pass;
|
||||||
p_results[index]=E->key()->owner;
|
p_results[index]=E->key()->owner;
|
||||||
p_result_indices[index]=E->key()->subindex;
|
p_result_indices[index]=E->key()->subindex;
|
||||||
|
@ -468,7 +483,7 @@ int BroadPhase2DHashGrid::cull_segment(const Vector2& p_from, const Vector2& p_t
|
||||||
max.y= (Math::floor(pos.y + 1)*cell_size - p_from.y) / dir.y;
|
max.y= (Math::floor(pos.y + 1)*cell_size - p_from.y) / dir.y;
|
||||||
|
|
||||||
int cullcount=0;
|
int cullcount=0;
|
||||||
_cull(pos,p_results,p_max_results,p_result_indices,cullcount);
|
_cull<false,true>(pos,Rect2(),p_from,p_to,p_results,p_max_results,p_result_indices,cullcount);
|
||||||
|
|
||||||
bool reached_x=false;
|
bool reached_x=false;
|
||||||
bool reached_y=false;
|
bool reached_y=false;
|
||||||
|
@ -502,7 +517,7 @@ int BroadPhase2DHashGrid::cull_segment(const Vector2& p_from, const Vector2& p_t
|
||||||
reached_y=true;
|
reached_y=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_cull(pos,p_results,p_max_results,p_result_indices,cullcount);
|
_cull<false,true>(pos,Rect2(),p_from,p_to,p_results,p_max_results,p_result_indices,cullcount);
|
||||||
|
|
||||||
if (reached_x && reached_y)
|
if (reached_x && reached_y)
|
||||||
break;
|
break;
|
||||||
|
@ -515,8 +530,22 @@ int BroadPhase2DHashGrid::cull_segment(const Vector2& p_from, const Vector2& p_t
|
||||||
|
|
||||||
int BroadPhase2DHashGrid::cull_aabb(const Rect2& p_aabb,CollisionObject2DSW** p_results,int p_max_results,int *p_result_indices) {
|
int BroadPhase2DHashGrid::cull_aabb(const Rect2& p_aabb,CollisionObject2DSW** p_results,int p_max_results,int *p_result_indices) {
|
||||||
|
|
||||||
|
pass++;
|
||||||
|
|
||||||
return 0;
|
Point2i from = (p_aabb.pos/cell_size).floor();
|
||||||
|
Point2i to = ((p_aabb.pos+p_aabb.size)/cell_size).floor();
|
||||||
|
int cullcount=0;
|
||||||
|
|
||||||
|
for(int i=from.x;i<=to.x;i++) {
|
||||||
|
|
||||||
|
for(int j=from.y;j<=to.y;j++) {
|
||||||
|
|
||||||
|
_cull<true,false>(Point2i(i,j),p_aabb,Point2(),Point2(),p_results,p_max_results,p_result_indices,cullcount);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return cullcount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BroadPhase2DHashGrid::set_pair_callback(PairCallback p_pair_callback,void *p_userdata) {
|
void BroadPhase2DHashGrid::set_pair_callback(PairCallback p_pair_callback,void *p_userdata) {
|
||||||
|
|
|
@ -94,7 +94,8 @@ class BroadPhase2DHashGrid : public BroadPhase2DSW {
|
||||||
|
|
||||||
void _enter_grid(Element* p_elem, const Rect2& p_rect,bool p_static);
|
void _enter_grid(Element* p_elem, const Rect2& p_rect,bool p_static);
|
||||||
void _exit_grid(Element* p_elem, const Rect2& p_rect,bool p_static);
|
void _exit_grid(Element* p_elem, const Rect2& p_rect,bool p_static);
|
||||||
_FORCE_INLINE_ void _cull(const Point2i p_cell,CollisionObject2DSW** p_results,int p_max_results,int *p_result_indices,int &index);
|
template<bool use_aabb,bool use_segment>
|
||||||
|
_FORCE_INLINE_ void _cull(const Point2i p_cell,const Rect2& p_aabb,const Point2& p_from, const Point2& p_to,CollisionObject2DSW** p_results,int p_max_results,int *p_result_indices,int &index);
|
||||||
|
|
||||||
|
|
||||||
struct PosKey {
|
struct PosKey {
|
||||||
|
|
|
@ -130,6 +130,7 @@ void CollisionObject2DSW::_update_shapes() {
|
||||||
if (!space)
|
if (!space)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
for(int i=0;i<shapes.size();i++) {
|
for(int i=0;i<shapes.size();i++) {
|
||||||
|
|
||||||
Shape &s=shapes[i];
|
Shape &s=shapes[i];
|
||||||
|
|
|
@ -55,8 +55,10 @@ private:
|
||||||
BroadPhase2DSW::ID bpid;
|
BroadPhase2DSW::ID bpid;
|
||||||
Rect2 aabb_cache; //for rayqueries
|
Rect2 aabb_cache; //for rayqueries
|
||||||
Shape2DSW *shape;
|
Shape2DSW *shape;
|
||||||
|
Vector2 kinematic_advance;
|
||||||
|
float kinematic_retreat;
|
||||||
bool trigger;
|
bool trigger;
|
||||||
Shape() { trigger=false; }
|
Shape() { trigger=false; kinematic_retreat=0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
Vector<Shape> shapes;
|
Vector<Shape> shapes;
|
||||||
|
@ -73,7 +75,7 @@ protected:
|
||||||
void _update_shapes_with_motion(const Vector2& p_motion);
|
void _update_shapes_with_motion(const Vector2& p_motion);
|
||||||
void _unregister_shapes();
|
void _unregister_shapes();
|
||||||
|
|
||||||
_FORCE_INLINE_ void _set_transform(const Matrix32& p_transform) { transform=p_transform; _update_shapes(); }
|
_FORCE_INLINE_ void _set_transform(const Matrix32& p_transform, bool p_update_shapes=true) { transform=p_transform; if (p_update_shapes) {_update_shapes();} }
|
||||||
_FORCE_INLINE_ void _set_inv_transform(const Matrix32& p_transform) { inv_transform=p_transform; }
|
_FORCE_INLINE_ void _set_inv_transform(const Matrix32& p_transform) { inv_transform=p_transform; }
|
||||||
void _set_static(bool p_static);
|
void _set_static(bool p_static);
|
||||||
|
|
||||||
|
@ -101,6 +103,12 @@ public:
|
||||||
_FORCE_INLINE_ const Matrix32& get_shape_inv_transform(int p_index) const { return shapes[p_index].xform_inv; }
|
_FORCE_INLINE_ const Matrix32& get_shape_inv_transform(int p_index) const { return shapes[p_index].xform_inv; }
|
||||||
_FORCE_INLINE_ const Rect2& get_shape_aabb(int p_index) const { return shapes[p_index].aabb_cache; }
|
_FORCE_INLINE_ const Rect2& get_shape_aabb(int p_index) const { return shapes[p_index].aabb_cache; }
|
||||||
|
|
||||||
|
_FORCE_INLINE_ void set_shape_kinematic_advance(int p_index,const Vector2& p_advance) { shapes[p_index].kinematic_advance=p_advance; }
|
||||||
|
_FORCE_INLINE_ Vector2 get_shape_kinematic_advance(int p_index) const { return shapes[p_index].kinematic_advance; }
|
||||||
|
|
||||||
|
_FORCE_INLINE_ void set_shape_kinematic_retreat(int p_index,float p_retreat) { shapes[p_index].kinematic_retreat=p_retreat; }
|
||||||
|
_FORCE_INLINE_ float get_shape_kinematic_retreat(int p_index) const { return shapes[p_index].kinematic_retreat; }
|
||||||
|
|
||||||
_FORCE_INLINE_ Matrix32 get_transform() const { return transform; }
|
_FORCE_INLINE_ Matrix32 get_transform() const { return transform; }
|
||||||
_FORCE_INLINE_ Matrix32 get_inv_transform() const { return inv_transform; }
|
_FORCE_INLINE_ Matrix32 get_inv_transform() const { return inv_transform; }
|
||||||
_FORCE_INLINE_ Space2DSW* get_space() const { return space; }
|
_FORCE_INLINE_ Space2DSW* get_space() const { return space; }
|
||||||
|
@ -109,6 +117,7 @@ public:
|
||||||
_FORCE_INLINE_ bool is_shape_set_as_trigger(int p_idx) const { return shapes[p_idx].trigger; }
|
_FORCE_INLINE_ bool is_shape_set_as_trigger(int p_idx) const { return shapes[p_idx].trigger; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void remove_shape(Shape2DSW *p_shape);
|
void remove_shape(Shape2DSW *p_shape);
|
||||||
void remove_shape(int p_index);
|
void remove_shape(int p_index);
|
||||||
|
|
||||||
|
|
|
@ -321,19 +321,19 @@ static void _generate_contacts_from_supports(const Vector2 * p_points_A,int p_po
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class ShapeA, class ShapeB>
|
template<class ShapeA, class ShapeB,bool castA=false,bool castB=false>
|
||||||
class SeparatorAxisTest2D {
|
class SeparatorAxisTest2D {
|
||||||
|
|
||||||
const ShapeA *shape_A;
|
const ShapeA *shape_A;
|
||||||
const ShapeB *shape_B;
|
const ShapeB *shape_B;
|
||||||
const Matrix32 *transform_A;
|
const Matrix32 *transform_A;
|
||||||
const Matrix32 *transform_B;
|
const Matrix32 *transform_B;
|
||||||
const Matrix32 *transform_inv_A;
|
|
||||||
const Matrix32 *transform_inv_B;
|
|
||||||
real_t best_depth;
|
real_t best_depth;
|
||||||
Vector2 best_axis;
|
Vector2 best_axis;
|
||||||
int best_axis_count;
|
int best_axis_count;
|
||||||
int best_axis_index;
|
int best_axis_index;
|
||||||
|
Vector2 motion_A;
|
||||||
|
Vector2 motion_B;
|
||||||
_CollectorCallback2D *callback;
|
_CollectorCallback2D *callback;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -351,6 +351,29 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ bool test_cast() {
|
||||||
|
|
||||||
|
if (castA) {
|
||||||
|
|
||||||
|
Vector2 na = motion_A.normalized();
|
||||||
|
if (!test_axis(na))
|
||||||
|
return false;
|
||||||
|
if (!test_axis(na.tangent()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (castB) {
|
||||||
|
|
||||||
|
Vector2 nb = motion_B.normalized();
|
||||||
|
if (!test_axis(nb))
|
||||||
|
return false;
|
||||||
|
if (!test_axis(nb.tangent()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
_FORCE_INLINE_ bool test_axis(const Vector2& p_axis) {
|
_FORCE_INLINE_ bool test_axis(const Vector2& p_axis) {
|
||||||
|
|
||||||
Vector2 axis=p_axis;
|
Vector2 axis=p_axis;
|
||||||
|
@ -364,8 +387,15 @@ public:
|
||||||
|
|
||||||
real_t min_A,max_A,min_B,max_B;
|
real_t min_A,max_A,min_B,max_B;
|
||||||
|
|
||||||
shape_A->project_range(axis,*transform_A,min_A,max_A);
|
if (castA)
|
||||||
shape_B->project_range(axis,*transform_B,min_B,max_B);
|
shape_A->project_range_cast(motion_A,axis,*transform_A,min_A,max_A);
|
||||||
|
else
|
||||||
|
shape_A->project_range(axis,*transform_A,min_A,max_A);
|
||||||
|
|
||||||
|
if (castB)
|
||||||
|
shape_B->project_range_cast(motion_B,axis,*transform_B,min_B,max_B);
|
||||||
|
else
|
||||||
|
shape_B->project_range(axis,*transform_B,min_B,max_B);
|
||||||
|
|
||||||
min_B -= ( max_A - min_A ) * 0.5;
|
min_B -= ( max_A - min_A ) * 0.5;
|
||||||
max_B += ( max_A - min_A ) * 0.5;
|
max_B += ( max_A - min_A ) * 0.5;
|
||||||
|
@ -427,21 +457,28 @@ public:
|
||||||
return; //only collide, no callback
|
return; //only collide, no callback
|
||||||
static const int max_supports=2;
|
static const int max_supports=2;
|
||||||
|
|
||||||
|
|
||||||
Vector2 supports_A[max_supports];
|
Vector2 supports_A[max_supports];
|
||||||
int support_count_A;
|
int support_count_A;
|
||||||
shape_A->get_supports(transform_A->basis_xform_inv(-best_axis).normalized(),supports_A,support_count_A);
|
if (castA) {
|
||||||
for(int i=0;i<support_count_A;i++) {
|
shape_A->get_supports_transformed_cast(motion_A,-best_axis,*transform_A,supports_A,support_count_A);
|
||||||
supports_A[i] = transform_A->xform(supports_A[i]);
|
} else {
|
||||||
|
shape_A->get_supports(transform_A->basis_xform_inv(-best_axis).normalized(),supports_A,support_count_A);
|
||||||
|
for(int i=0;i<support_count_A;i++) {
|
||||||
|
supports_A[i] = transform_A->xform(supports_A[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Vector2 supports_B[max_supports];
|
Vector2 supports_B[max_supports];
|
||||||
int support_count_B;
|
int support_count_B;
|
||||||
shape_B->get_supports(transform_B->basis_xform_inv(best_axis).normalized(),supports_B,support_count_B);
|
if (castB) {
|
||||||
for(int i=0;i<support_count_B;i++) {
|
shape_B->get_supports_transformed_cast(motion_B,best_axis,*transform_B,supports_B,support_count_B);
|
||||||
supports_B[i] = transform_B->xform(supports_B[i]);
|
} else {
|
||||||
|
shape_B->get_supports(transform_B->basis_xform_inv(best_axis).normalized(),supports_B,support_count_B);
|
||||||
|
for(int i=0;i<support_count_B;i++) {
|
||||||
|
supports_B[i] = transform_B->xform(supports_B[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
||||||
|
@ -480,14 +517,15 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_FORCE_INLINE_ SeparatorAxisTest2D(const ShapeA *p_shape_A,const Matrix32& p_transform_a,const Matrix32& p_transform_inv_a, const ShapeB *p_shape_B,const Matrix32& p_transform_b,const Matrix32& p_transform_inv_b,_CollectorCallback2D *p_collector) {
|
_FORCE_INLINE_ SeparatorAxisTest2D(const ShapeA *p_shape_A,const Matrix32& p_transform_a, const ShapeB *p_shape_B,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_A=Vector2(), const Vector2& p_motion_B=Vector2()) {
|
||||||
best_depth=1e15;
|
best_depth=1e15;
|
||||||
shape_A=p_shape_A;
|
shape_A=p_shape_A;
|
||||||
shape_B=p_shape_B;
|
shape_B=p_shape_B;
|
||||||
transform_A=&p_transform_a;
|
transform_A=&p_transform_a;
|
||||||
transform_B=&p_transform_b;
|
transform_B=&p_transform_b;
|
||||||
transform_inv_A=&p_transform_inv_a;
|
motion_A=p_motion_A;
|
||||||
transform_inv_B=&p_transform_inv_b;
|
motion_B=p_motion_B;
|
||||||
|
|
||||||
callback=p_collector;
|
callback=p_collector;
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
best_axis_count=0;
|
best_axis_count=0;
|
||||||
|
@ -503,68 +541,92 @@ public:
|
||||||
/****** SAT TESTS *******/
|
/****** SAT TESTS *******/
|
||||||
|
|
||||||
|
|
||||||
typedef void (*CollisionFunc)(const Shape2DSW*,const Matrix32&,const Matrix32&,const Shape2DSW*,const Matrix32&,const Matrix32&,_CollectorCallback2D *p_collector);
|
#define TEST_POINT(m_a,m_b) \
|
||||||
|
( (!separator.test_axis(((m_a)-(m_b)).normalized())) ||\
|
||||||
|
(castA && !separator.test_axis(((m_a)+p_motion_a-(m_b)).normalized())) ||\
|
||||||
|
(castB && !separator.test_axis(((m_a)-((m_b)+p_motion_b)).normalized())) ||\
|
||||||
|
(castA && castB && !separator.test_axis(((m_a)+p_motion_a-((m_b)+p_motion_b)).normalized())) )
|
||||||
|
|
||||||
static void _collision_segment_segment(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Matrix32& p_transform_inv_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,const Matrix32& p_transform_inv_b,_CollectorCallback2D *p_collector) {
|
|
||||||
|
typedef void (*CollisionFunc)(const Shape2DSW*,const Matrix32&,const Shape2DSW*,const Matrix32&,_CollectorCallback2D *p_collector,const Vector2&,const Vector2&);
|
||||||
|
|
||||||
|
|
||||||
|
template<bool castA, bool castB>
|
||||||
|
static void _collision_segment_segment(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b) {
|
||||||
|
|
||||||
const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW*>(p_a);
|
const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW*>(p_a);
|
||||||
const SegmentShape2DSW *segment_B = static_cast<const SegmentShape2DSW*>(p_b);
|
const SegmentShape2DSW *segment_B = static_cast<const SegmentShape2DSW*>(p_b);
|
||||||
|
|
||||||
SeparatorAxisTest2D<SegmentShape2DSW,SegmentShape2DSW> separator(segment_A,p_transform_a,p_transform_inv_a,segment_B,p_transform_b,p_transform_inv_b,p_collector);
|
SeparatorAxisTest2D<SegmentShape2DSW,SegmentShape2DSW,castA,castB> separator(segment_A,p_transform_a,segment_B,p_transform_b,p_collector,p_motion_a,p_motion_b);
|
||||||
|
|
||||||
|
if (!separator.test_previous_axis())
|
||||||
|
return;
|
||||||
|
//this collision is kind of pointless
|
||||||
|
|
||||||
|
|
||||||
if (!separator.test_previous_axis())
|
if (!separator.test_previous_axis())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!separator.test_axis(p_transform_inv_a.basis_xform_inv(segment_A->get_normal()).normalized()))
|
if (!separator.test_cast())
|
||||||
return;
|
return;
|
||||||
if (!separator.test_axis(p_transform_inv_a.basis_xform_inv(segment_B->get_normal()).normalized()))
|
|
||||||
|
if (!separator.test_axis(segment_A->get_xformed_normal(p_transform_a)))
|
||||||
|
return;
|
||||||
|
if (!separator.test_axis(segment_B->get_xformed_normal(p_transform_b)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
separator.generate_contacts();
|
separator.generate_contacts();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _collision_segment_circle(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Matrix32& p_transform_inv_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,const Matrix32& p_transform_inv_b,_CollectorCallback2D *p_collector) {
|
template<bool castA, bool castB>
|
||||||
|
static void _collision_segment_circle(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b) {
|
||||||
|
|
||||||
|
|
||||||
const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW*>(p_a);
|
const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW*>(p_a);
|
||||||
const CircleShape2DSW *circle_B = static_cast<const CircleShape2DSW*>(p_b);
|
const CircleShape2DSW *circle_B = static_cast<const CircleShape2DSW*>(p_b);
|
||||||
|
|
||||||
|
|
||||||
SeparatorAxisTest2D<SegmentShape2DSW,CircleShape2DSW> separator(segment_A,p_transform_a,p_transform_inv_a,circle_B,p_transform_b,p_transform_inv_b,p_collector);
|
SeparatorAxisTest2D<SegmentShape2DSW,CircleShape2DSW,castA,castB> separator(segment_A,p_transform_a,circle_B,p_transform_b,p_collector,p_motion_a,p_motion_b);
|
||||||
|
|
||||||
if (!separator.test_previous_axis())
|
if (!separator.test_previous_axis())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!separator.test_cast())
|
||||||
|
return;
|
||||||
|
|
||||||
|
//segment normal
|
||||||
if (!separator.test_axis(
|
if (!separator.test_axis(
|
||||||
(p_transform_a.xform(segment_A->get_b())-p_transform_a.xform(segment_A->get_a())).normalized().tangent()
|
(p_transform_a.xform(segment_A->get_b())-p_transform_a.xform(segment_A->get_a())).normalized().tangent()
|
||||||
))
|
))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// if (!separator.test_axis(p_transform_inv_a.basis_xform_inv(segment_A->get_normal()).normalized()))
|
//endpoint a vs circle
|
||||||
// return;
|
if (TEST_POINT(p_transform_a.xform(segment_A->get_a()),p_transform_b.get_origin()))
|
||||||
if (!separator.test_axis((p_transform_a.xform(segment_A->get_a())-p_transform_b.get_origin()).normalized()))
|
|
||||||
return;
|
return;
|
||||||
if (!separator.test_axis((p_transform_a.xform(segment_A->get_b())-p_transform_b.get_origin()).normalized()))
|
//endpoint b vs circle
|
||||||
|
if (TEST_POINT(p_transform_a.xform(segment_A->get_b()),p_transform_b.get_origin()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
separator.generate_contacts();
|
separator.generate_contacts();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _collision_segment_rectangle(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Matrix32& p_transform_inv_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,const Matrix32& p_transform_inv_b,_CollectorCallback2D *p_collector) {
|
template<bool castA, bool castB>
|
||||||
|
static void _collision_segment_rectangle(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b) {
|
||||||
|
|
||||||
const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW*>(p_a);
|
const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW*>(p_a);
|
||||||
const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW*>(p_b);
|
const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW*>(p_b);
|
||||||
|
|
||||||
SeparatorAxisTest2D<SegmentShape2DSW,RectangleShape2DSW> separator(segment_A,p_transform_a,p_transform_inv_a,rectangle_B,p_transform_b,p_transform_inv_b,p_collector);
|
SeparatorAxisTest2D<SegmentShape2DSW,RectangleShape2DSW,castA,castB> separator(segment_A,p_transform_a,rectangle_B,p_transform_b,p_collector,p_motion_a,p_motion_b);
|
||||||
|
|
||||||
if (!separator.test_previous_axis())
|
if (!separator.test_previous_axis())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!separator.test_axis(p_transform_inv_a.basis_xform_inv(segment_A->get_normal()).normalized()))
|
if (!separator.test_cast())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!separator.test_axis(segment_A->get_xformed_normal(p_transform_a)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!separator.test_axis(p_transform_b.elements[0].normalized()))
|
if (!separator.test_axis(p_transform_b.elements[0].normalized()))
|
||||||
|
@ -577,50 +639,58 @@ static void _collision_segment_rectangle(const Shape2DSW* p_a,const Matrix32& p_
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _collision_segment_capsule(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Matrix32& p_transform_inv_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,const Matrix32& p_transform_inv_b,_CollectorCallback2D *p_collector) {
|
template<bool castA, bool castB>
|
||||||
|
static void _collision_segment_capsule(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b) {
|
||||||
|
|
||||||
const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW*>(p_a);
|
const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW*>(p_a);
|
||||||
const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW*>(p_b);
|
const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW*>(p_b);
|
||||||
|
|
||||||
SeparatorAxisTest2D<SegmentShape2DSW,CapsuleShape2DSW> separator(segment_A,p_transform_a,p_transform_inv_a,capsule_B,p_transform_b,p_transform_inv_b,p_collector);
|
SeparatorAxisTest2D<SegmentShape2DSW,CapsuleShape2DSW,castA,castB> separator(segment_A,p_transform_a,capsule_B,p_transform_b,p_collector,p_motion_a,p_motion_b);
|
||||||
|
|
||||||
if (!separator.test_previous_axis())
|
if (!separator.test_previous_axis())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!separator.test_axis(p_transform_inv_a.basis_xform_inv(segment_A->get_normal()).normalized()))
|
if (!separator.test_cast())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!separator.test_axis(segment_A->get_xformed_normal(p_transform_a)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!separator.test_axis(p_transform_b.elements[0].normalized()))
|
if (!separator.test_axis(p_transform_b.elements[0].normalized()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!separator.test_axis((p_transform_a.xform(segment_A->get_a())-(p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*0.5)).normalized()))
|
if (TEST_POINT(p_transform_a.xform(segment_A->get_a()),(p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*0.5)))
|
||||||
return;
|
return;
|
||||||
if (!separator.test_axis((p_transform_a.xform(segment_A->get_a())-(p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*-0.5)).normalized()))
|
if (TEST_POINT(p_transform_a.xform(segment_A->get_a()),(p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*-0.5)))
|
||||||
return;
|
return;
|
||||||
if (!separator.test_axis((p_transform_a.xform(segment_A->get_b())-(p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*0.5)).normalized()))
|
if (TEST_POINT(p_transform_a.xform(segment_A->get_b()),(p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*0.5)))
|
||||||
return;
|
return;
|
||||||
if (!separator.test_axis((p_transform_a.xform(segment_A->get_b())-(p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*-0.5)).normalized()))
|
if (TEST_POINT(p_transform_a.xform(segment_A->get_b()),(p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*-0.5)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
separator.generate_contacts();
|
separator.generate_contacts();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _collision_segment_convex_polygon(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Matrix32& p_transform_inv_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,const Matrix32& p_transform_inv_b,_CollectorCallback2D *p_collector) {
|
template<bool castA, bool castB>
|
||||||
|
static void _collision_segment_convex_polygon(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b) {
|
||||||
|
|
||||||
const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW*>(p_a);
|
const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW*>(p_a);
|
||||||
const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW*>(p_b);
|
const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW*>(p_b);
|
||||||
|
|
||||||
SeparatorAxisTest2D<SegmentShape2DSW,ConvexPolygonShape2DSW> separator(segment_A,p_transform_a,p_transform_inv_a,convex_B,p_transform_b,p_transform_inv_b,p_collector);
|
SeparatorAxisTest2D<SegmentShape2DSW,ConvexPolygonShape2DSW,castA,castB> separator(segment_A,p_transform_a,convex_B,p_transform_b,p_collector,p_motion_a,p_motion_b);
|
||||||
|
|
||||||
if (!separator.test_previous_axis())
|
if (!separator.test_previous_axis())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!separator.test_axis(p_transform_inv_a.basis_xform_inv(segment_A->get_normal()).normalized()))
|
if (!separator.test_cast())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!separator.test_axis(segment_A->get_xformed_normal(p_transform_a)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for(int i=0;i<convex_B->get_point_count();i++) {
|
for(int i=0;i<convex_B->get_point_count();i++) {
|
||||||
|
|
||||||
if (!separator.test_axis( p_transform_inv_b.basis_xform_inv(convex_B->get_segment_normal(i)).normalized() ))
|
if (!separator.test_axis( convex_B->get_xformed_segment_normal(p_transform_b,i)))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -631,35 +701,44 @@ static void _collision_segment_convex_polygon(const Shape2DSW* p_a,const Matrix3
|
||||||
|
|
||||||
/////////
|
/////////
|
||||||
|
|
||||||
static void _collision_circle_circle(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Matrix32& p_transform_inv_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,const Matrix32& p_transform_inv_b,_CollectorCallback2D *p_collector) {
|
template<bool castA, bool castB>
|
||||||
|
static void _collision_circle_circle(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b) {
|
||||||
|
|
||||||
const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW*>(p_a);
|
const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW*>(p_a);
|
||||||
const CircleShape2DSW *circle_B = static_cast<const CircleShape2DSW*>(p_b);
|
const CircleShape2DSW *circle_B = static_cast<const CircleShape2DSW*>(p_b);
|
||||||
|
|
||||||
|
|
||||||
SeparatorAxisTest2D<CircleShape2DSW,CircleShape2DSW> separator(circle_A,p_transform_a,p_transform_inv_a,circle_B,p_transform_b,p_transform_inv_b,p_collector);
|
SeparatorAxisTest2D<CircleShape2DSW,CircleShape2DSW,castA,castB> separator(circle_A,p_transform_a,circle_B,p_transform_b,p_collector,p_motion_a,p_motion_b);
|
||||||
|
|
||||||
if (!separator.test_previous_axis())
|
if (!separator.test_previous_axis())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!separator.test_axis((p_transform_a.get_origin()-p_transform_b.get_origin()).normalized()))
|
if (!separator.test_cast())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (TEST_POINT(p_transform_a.get_origin(),p_transform_b.get_origin()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
separator.generate_contacts();
|
separator.generate_contacts();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _collision_circle_rectangle(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Matrix32& p_transform_inv_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,const Matrix32& p_transform_inv_b,_CollectorCallback2D *p_collector) {
|
template<bool castA, bool castB>
|
||||||
|
static void _collision_circle_rectangle(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b) {
|
||||||
|
|
||||||
const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW*>(p_a);
|
const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW*>(p_a);
|
||||||
const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW*>(p_b);
|
const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW*>(p_b);
|
||||||
|
|
||||||
|
|
||||||
SeparatorAxisTest2D<CircleShape2DSW,RectangleShape2DSW> separator(circle_A,p_transform_a,p_transform_inv_a,rectangle_B,p_transform_b,p_transform_inv_b,p_collector);
|
SeparatorAxisTest2D<CircleShape2DSW,RectangleShape2DSW,castA,castB> separator(circle_A,p_transform_a,rectangle_B,p_transform_b,p_collector,p_motion_a,p_motion_b);
|
||||||
|
|
||||||
if (!separator.test_previous_axis())
|
if (!separator.test_previous_axis())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!separator.test_cast())
|
||||||
|
return;
|
||||||
|
|
||||||
const Vector2 &sphere=p_transform_a.elements[2];
|
const Vector2 &sphere=p_transform_a.elements[2];
|
||||||
const Vector2 *axis=&p_transform_b.elements[0];
|
const Vector2 *axis=&p_transform_b.elements[0];
|
||||||
const Vector2& half_extents = rectangle_B->get_half_extents();
|
const Vector2& half_extents = rectangle_B->get_half_extents();
|
||||||
|
@ -670,65 +749,120 @@ static void _collision_circle_rectangle(const Shape2DSW* p_a,const Matrix32& p_t
|
||||||
if (!separator.test_axis(axis[1].normalized()))
|
if (!separator.test_axis(axis[1].normalized()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Vector2 local_v = p_transform_inv_b.xform(p_transform_a.get_origin());
|
{
|
||||||
|
Vector2 local_v = p_transform_b.affine_inverse().xform(p_transform_a.get_origin());
|
||||||
|
|
||||||
Vector2 he(
|
Vector2 he(
|
||||||
(local_v.x<0) ? -half_extents.x : half_extents.x,
|
(local_v.x<0) ? -half_extents.x : half_extents.x,
|
||||||
(local_v.y<0) ? -half_extents.y : half_extents.y
|
(local_v.y<0) ? -half_extents.y : half_extents.y
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
if (!separator.test_axis((p_transform_b.xform(he)-sphere).normalized()))
|
if (!separator.test_axis((p_transform_b.xform(he)-sphere).normalized()))
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (castA) {
|
||||||
|
|
||||||
|
Vector2 sphereofs = sphere + p_motion_a;
|
||||||
|
Vector2 local_v = p_transform_b.affine_inverse().xform(sphereofs);
|
||||||
|
|
||||||
|
Vector2 he(
|
||||||
|
(local_v.x<0) ? -half_extents.x : half_extents.x,
|
||||||
|
(local_v.y<0) ? -half_extents.y : half_extents.y
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
if (!separator.test_axis((p_transform_b.xform(he)-sphereofs).normalized()))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (castB) {
|
||||||
|
|
||||||
|
Vector2 sphereofs = sphere - p_motion_b;
|
||||||
|
Vector2 local_v = p_transform_b.affine_inverse().xform(sphereofs);
|
||||||
|
|
||||||
|
Vector2 he(
|
||||||
|
(local_v.x<0) ? -half_extents.x : half_extents.x,
|
||||||
|
(local_v.y<0) ? -half_extents.y : half_extents.y
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
if (!separator.test_axis((p_transform_b.xform(he)-sphereofs).normalized()))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (castA && castB) {
|
||||||
|
|
||||||
|
Vector2 sphereofs = sphere - p_motion_b + p_motion_a;
|
||||||
|
Vector2 local_v = p_transform_b.affine_inverse().xform(sphereofs);
|
||||||
|
|
||||||
|
Vector2 he(
|
||||||
|
(local_v.x<0) ? -half_extents.x : half_extents.x,
|
||||||
|
(local_v.y<0) ? -half_extents.y : half_extents.y
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
if (!separator.test_axis((p_transform_b.xform(he)-sphereofs).normalized()))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
separator.generate_contacts();
|
separator.generate_contacts();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _collision_circle_capsule(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Matrix32& p_transform_inv_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,const Matrix32& p_transform_inv_b,_CollectorCallback2D *p_collector) {
|
template<bool castA, bool castB>
|
||||||
|
static void _collision_circle_capsule(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b) {
|
||||||
|
|
||||||
const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW*>(p_a);
|
const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW*>(p_a);
|
||||||
const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW*>(p_b);
|
const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW*>(p_b);
|
||||||
|
|
||||||
|
|
||||||
SeparatorAxisTest2D<CircleShape2DSW,CapsuleShape2DSW> separator(circle_A,p_transform_a,p_transform_inv_a,capsule_B,p_transform_b,p_transform_inv_b,p_collector);
|
SeparatorAxisTest2D<CircleShape2DSW,CapsuleShape2DSW,castA,castB> separator(circle_A,p_transform_a,capsule_B,p_transform_b,p_collector,p_motion_a,p_motion_b);
|
||||||
|
|
||||||
if (!separator.test_previous_axis())
|
if (!separator.test_previous_axis())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!separator.test_cast())
|
||||||
|
return;
|
||||||
|
|
||||||
//capsule axis
|
//capsule axis
|
||||||
if (!separator.test_axis(p_transform_b.elements[0].normalized()))
|
if (!separator.test_axis(p_transform_b.elements[0].normalized()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//capsule endpoints
|
//capsule endpoints
|
||||||
if (!separator.test_axis((p_transform_a.get_origin()-(p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*0.5)).normalized()))
|
if (TEST_POINT(p_transform_a.get_origin(),(p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*0.5)))
|
||||||
return;
|
return;
|
||||||
if (!separator.test_axis((p_transform_a.get_origin()-(p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*-0.5)).normalized()))
|
if (TEST_POINT(p_transform_a.get_origin(),(p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*-0.5)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
separator.generate_contacts();
|
separator.generate_contacts();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _collision_circle_convex_polygon(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Matrix32& p_transform_inv_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,const Matrix32& p_transform_inv_b,_CollectorCallback2D *p_collector) {
|
template<bool castA, bool castB>
|
||||||
|
static void _collision_circle_convex_polygon(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b) {
|
||||||
|
|
||||||
const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW*>(p_a);
|
const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW*>(p_a);
|
||||||
const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW*>(p_b);
|
const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW*>(p_b);
|
||||||
|
|
||||||
|
|
||||||
SeparatorAxisTest2D<CircleShape2DSW,ConvexPolygonShape2DSW> separator(circle_A,p_transform_a,p_transform_inv_a,convex_B,p_transform_b,p_transform_inv_b,p_collector);
|
SeparatorAxisTest2D<CircleShape2DSW,ConvexPolygonShape2DSW,castA,castB> separator(circle_A,p_transform_a,convex_B,p_transform_b,p_collector,p_motion_a,p_motion_b);
|
||||||
|
|
||||||
if (!separator.test_previous_axis())
|
if (!separator.test_previous_axis())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!separator.test_cast())
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
//poly faces and poly points vs circle
|
//poly faces and poly points vs circle
|
||||||
for(int i=0;i<convex_B->get_point_count();i++) {
|
for(int i=0;i<convex_B->get_point_count();i++) {
|
||||||
|
|
||||||
if (!separator.test_axis( (p_transform_b.xform(convex_B->get_point(i))-p_transform_a.get_origin()).normalized() ))
|
if (TEST_POINT( p_transform_a.get_origin(),p_transform_b.xform(convex_B->get_point(i)) ))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!separator.test_axis( p_transform_inv_b.basis_xform_inv(convex_B->get_segment_normal(i)).normalized() ))
|
if (!separator.test_axis( convex_B->get_xformed_segment_normal(p_transform_b,i)))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -738,17 +872,21 @@ static void _collision_circle_convex_polygon(const Shape2DSW* p_a,const Matrix32
|
||||||
|
|
||||||
/////////
|
/////////
|
||||||
|
|
||||||
static void _collision_rectangle_rectangle(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Matrix32& p_transform_inv_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,const Matrix32& p_transform_inv_b,_CollectorCallback2D *p_collector) {
|
template<bool castA, bool castB>
|
||||||
|
static void _collision_rectangle_rectangle(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b) {
|
||||||
|
|
||||||
const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW*>(p_a);
|
const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW*>(p_a);
|
||||||
const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW*>(p_b);
|
const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW*>(p_b);
|
||||||
|
|
||||||
|
|
||||||
SeparatorAxisTest2D<RectangleShape2DSW,RectangleShape2DSW> separator(rectangle_A,p_transform_a,p_transform_inv_a,rectangle_B,p_transform_b,p_transform_inv_b,p_collector);
|
SeparatorAxisTest2D<RectangleShape2DSW,RectangleShape2DSW,castA,castB> separator(rectangle_A,p_transform_a,rectangle_B,p_transform_b,p_collector,p_motion_a,p_motion_b);
|
||||||
|
|
||||||
if (!separator.test_previous_axis())
|
if (!separator.test_previous_axis())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!separator.test_cast())
|
||||||
|
return;
|
||||||
|
|
||||||
//box faces A
|
//box faces A
|
||||||
if (!separator.test_axis(p_transform_a.elements[0].normalized()))
|
if (!separator.test_axis(p_transform_a.elements[0].normalized()))
|
||||||
return;
|
return;
|
||||||
|
@ -766,17 +904,21 @@ static void _collision_rectangle_rectangle(const Shape2DSW* p_a,const Matrix32&
|
||||||
separator.generate_contacts();
|
separator.generate_contacts();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _collision_rectangle_capsule(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Matrix32& p_transform_inv_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,const Matrix32& p_transform_inv_b,_CollectorCallback2D *p_collector) {
|
template<bool castA, bool castB>
|
||||||
|
static void _collision_rectangle_capsule(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b) {
|
||||||
|
|
||||||
const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW*>(p_a);
|
const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW*>(p_a);
|
||||||
const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW*>(p_b);
|
const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW*>(p_b);
|
||||||
|
|
||||||
|
|
||||||
SeparatorAxisTest2D<RectangleShape2DSW,CapsuleShape2DSW> separator(rectangle_A,p_transform_a,p_transform_inv_a,capsule_B,p_transform_b,p_transform_inv_b,p_collector);
|
SeparatorAxisTest2D<RectangleShape2DSW,CapsuleShape2DSW,castA,castB> separator(rectangle_A,p_transform_a,capsule_B,p_transform_b,p_collector,p_motion_a,p_motion_b);
|
||||||
|
|
||||||
if (!separator.test_previous_axis())
|
if (!separator.test_previous_axis())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!separator.test_cast())
|
||||||
|
return;
|
||||||
|
|
||||||
//box faces
|
//box faces
|
||||||
if (!separator.test_axis(p_transform_a.elements[0].normalized()))
|
if (!separator.test_axis(p_transform_a.elements[0].normalized()))
|
||||||
return;
|
return;
|
||||||
|
@ -791,21 +933,77 @@ static void _collision_rectangle_capsule(const Shape2DSW* p_a,const Matrix32& p_
|
||||||
|
|
||||||
//box endpoints to capsule circles
|
//box endpoints to capsule circles
|
||||||
|
|
||||||
|
Matrix32 boxinv = p_transform_a.affine_inverse();
|
||||||
|
|
||||||
for(int i=0;i<2;i++) {
|
for(int i=0;i<2;i++) {
|
||||||
|
|
||||||
Vector2 capsule_endpoint = p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*(i==0?0.5:-0.5);
|
{
|
||||||
|
Vector2 capsule_endpoint = p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*(i==0?0.5:-0.5);
|
||||||
|
|
||||||
const Vector2& half_extents = rectangle_A->get_half_extents();
|
const Vector2& half_extents = rectangle_A->get_half_extents();
|
||||||
Vector2 local_v = p_transform_inv_a.xform(capsule_endpoint);
|
Vector2 local_v = boxinv.xform(capsule_endpoint);
|
||||||
|
|
||||||
Vector2 he(
|
Vector2 he(
|
||||||
(local_v.x<0) ? -half_extents.x : half_extents.x,
|
(local_v.x<0) ? -half_extents.x : half_extents.x,
|
||||||
(local_v.y<0) ? -half_extents.y : half_extents.y
|
(local_v.y<0) ? -half_extents.y : half_extents.y
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!separator.test_axis(p_transform_a.xform(he-capsule_endpoint).normalized()))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!separator.test_axis(p_transform_a.xform(he).normalized()))
|
if (castA) {
|
||||||
return;
|
Vector2 capsule_endpoint = p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*(i==0?0.5:-0.5);
|
||||||
|
capsule_endpoint-=p_motion_a;
|
||||||
|
|
||||||
|
|
||||||
|
const Vector2& half_extents = rectangle_A->get_half_extents();
|
||||||
|
Vector2 local_v = boxinv.xform(capsule_endpoint);
|
||||||
|
|
||||||
|
Vector2 he(
|
||||||
|
(local_v.x<0) ? -half_extents.x : half_extents.x,
|
||||||
|
(local_v.y<0) ? -half_extents.y : half_extents.y
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!separator.test_axis(p_transform_a.xform(he-capsule_endpoint).normalized()))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (castB) {
|
||||||
|
Vector2 capsule_endpoint = p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*(i==0?0.5:-0.5);
|
||||||
|
capsule_endpoint+=p_motion_b;
|
||||||
|
|
||||||
|
|
||||||
|
const Vector2& half_extents = rectangle_A->get_half_extents();
|
||||||
|
Vector2 local_v = boxinv.xform(capsule_endpoint);
|
||||||
|
|
||||||
|
Vector2 he(
|
||||||
|
(local_v.x<0) ? -half_extents.x : half_extents.x,
|
||||||
|
(local_v.y<0) ? -half_extents.y : half_extents.y
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!separator.test_axis(p_transform_a.xform(he-capsule_endpoint).normalized()))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (castA && castB) {
|
||||||
|
Vector2 capsule_endpoint = p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*(i==0?0.5:-0.5);
|
||||||
|
capsule_endpoint-=p_motion_a;
|
||||||
|
capsule_endpoint+=p_motion_b;
|
||||||
|
|
||||||
|
|
||||||
|
const Vector2& half_extents = rectangle_A->get_half_extents();
|
||||||
|
Vector2 local_v = boxinv.xform(capsule_endpoint);
|
||||||
|
|
||||||
|
Vector2 he(
|
||||||
|
(local_v.x<0) ? -half_extents.x : half_extents.x,
|
||||||
|
(local_v.y<0) ? -half_extents.y : half_extents.y
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!separator.test_axis(p_transform_a.xform(he-capsule_endpoint).normalized()))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -813,16 +1011,20 @@ static void _collision_rectangle_capsule(const Shape2DSW* p_a,const Matrix32& p_
|
||||||
separator.generate_contacts();
|
separator.generate_contacts();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _collision_rectangle_convex_polygon(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Matrix32& p_transform_inv_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,const Matrix32& p_transform_inv_b,_CollectorCallback2D *p_collector) {
|
template<bool castA, bool castB>
|
||||||
|
static void _collision_rectangle_convex_polygon(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b) {
|
||||||
|
|
||||||
const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW*>(p_a);
|
const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW*>(p_a);
|
||||||
const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW*>(p_b);
|
const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW*>(p_b);
|
||||||
|
|
||||||
SeparatorAxisTest2D<RectangleShape2DSW,ConvexPolygonShape2DSW> separator(rectangle_A,p_transform_a,p_transform_inv_a,convex_B,p_transform_b,p_transform_inv_b,p_collector);
|
SeparatorAxisTest2D<RectangleShape2DSW,ConvexPolygonShape2DSW,castA,castB> separator(rectangle_A,p_transform_a,convex_B,p_transform_b,p_collector,p_motion_a,p_motion_b);
|
||||||
|
|
||||||
if (!separator.test_previous_axis())
|
if (!separator.test_previous_axis())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!separator.test_cast())
|
||||||
|
return;
|
||||||
|
|
||||||
//box faces
|
//box faces
|
||||||
if (!separator.test_axis(p_transform_a.elements[0].normalized()))
|
if (!separator.test_axis(p_transform_a.elements[0].normalized()))
|
||||||
return;
|
return;
|
||||||
|
@ -833,7 +1035,7 @@ static void _collision_rectangle_convex_polygon(const Shape2DSW* p_a,const Matri
|
||||||
//convex faces
|
//convex faces
|
||||||
for(int i=0;i<convex_B->get_point_count();i++) {
|
for(int i=0;i<convex_B->get_point_count();i++) {
|
||||||
|
|
||||||
if (!separator.test_axis( p_transform_inv_b.basis_xform_inv(convex_B->get_segment_normal(i)).normalized() ))
|
if (!separator.test_axis( convex_B->get_xformed_segment_normal(p_transform_b,i)))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -844,17 +1046,21 @@ static void _collision_rectangle_convex_polygon(const Shape2DSW* p_a,const Matri
|
||||||
|
|
||||||
/////////
|
/////////
|
||||||
|
|
||||||
static void _collision_capsule_capsule(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Matrix32& p_transform_inv_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,const Matrix32& p_transform_inv_b,_CollectorCallback2D *p_collector) {
|
template<bool castA, bool castB>
|
||||||
|
static void _collision_capsule_capsule(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b) {
|
||||||
|
|
||||||
const CapsuleShape2DSW *capsule_A = static_cast<const CapsuleShape2DSW*>(p_a);
|
const CapsuleShape2DSW *capsule_A = static_cast<const CapsuleShape2DSW*>(p_a);
|
||||||
const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW*>(p_b);
|
const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW*>(p_b);
|
||||||
|
|
||||||
|
|
||||||
SeparatorAxisTest2D<CapsuleShape2DSW,CapsuleShape2DSW> separator(capsule_A,p_transform_a,p_transform_inv_a,capsule_B,p_transform_b,p_transform_inv_b,p_collector);
|
SeparatorAxisTest2D<CapsuleShape2DSW,CapsuleShape2DSW,castA,castB> separator(capsule_A,p_transform_a,capsule_B,p_transform_b,p_collector,p_motion_a,p_motion_b);
|
||||||
|
|
||||||
if (!separator.test_previous_axis())
|
if (!separator.test_previous_axis())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!separator.test_cast())
|
||||||
|
return;
|
||||||
|
|
||||||
//capsule axis
|
//capsule axis
|
||||||
|
|
||||||
if (!separator.test_axis(p_transform_b.elements[0].normalized()))
|
if (!separator.test_axis(p_transform_b.elements[0].normalized()))
|
||||||
|
@ -873,7 +1079,7 @@ static void _collision_capsule_capsule(const Shape2DSW* p_a,const Matrix32& p_tr
|
||||||
|
|
||||||
Vector2 capsule_endpoint_B = p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*(j==0?0.5:-0.5);
|
Vector2 capsule_endpoint_B = p_transform_b.get_origin()+p_transform_b.elements[1]*capsule_B->get_height()*(j==0?0.5:-0.5);
|
||||||
|
|
||||||
if (!separator.test_axis( (capsule_endpoint_A-capsule_endpoint_B).normalized() ))
|
if (TEST_POINT(capsule_endpoint_A,capsule_endpoint_B) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -883,17 +1089,21 @@ static void _collision_capsule_capsule(const Shape2DSW* p_a,const Matrix32& p_tr
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _collision_capsule_convex_polygon(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Matrix32& p_transform_inv_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,const Matrix32& p_transform_inv_b,_CollectorCallback2D *p_collector) {
|
template<bool castA, bool castB>
|
||||||
|
static void _collision_capsule_convex_polygon(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b) {
|
||||||
|
|
||||||
const CapsuleShape2DSW *capsule_A = static_cast<const CapsuleShape2DSW*>(p_a);
|
const CapsuleShape2DSW *capsule_A = static_cast<const CapsuleShape2DSW*>(p_a);
|
||||||
const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW*>(p_b);
|
const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW*>(p_b);
|
||||||
|
|
||||||
|
|
||||||
SeparatorAxisTest2D<CapsuleShape2DSW,ConvexPolygonShape2DSW> separator(capsule_A,p_transform_a,p_transform_inv_a,convex_B,p_transform_b,p_transform_inv_b,p_collector);
|
SeparatorAxisTest2D<CapsuleShape2DSW,ConvexPolygonShape2DSW,castA,castB> separator(capsule_A,p_transform_a,convex_B,p_transform_b,p_collector,p_motion_a,p_motion_b);
|
||||||
|
|
||||||
if (!separator.test_previous_axis())
|
if (!separator.test_previous_axis())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!separator.test_cast())
|
||||||
|
return;
|
||||||
|
|
||||||
//capsule axis
|
//capsule axis
|
||||||
|
|
||||||
if (!separator.test_axis(p_transform_a.elements[0].normalized()))
|
if (!separator.test_axis(p_transform_a.elements[0].normalized()))
|
||||||
|
@ -909,12 +1119,12 @@ static void _collision_capsule_convex_polygon(const Shape2DSW* p_a,const Matrix3
|
||||||
|
|
||||||
Vector2 capsule_endpoint_A = p_transform_a.get_origin()+p_transform_a.elements[1]*capsule_A->get_height()*(j==0?0.5:-0.5);
|
Vector2 capsule_endpoint_A = p_transform_a.get_origin()+p_transform_a.elements[1]*capsule_A->get_height()*(j==0?0.5:-0.5);
|
||||||
|
|
||||||
if (!separator.test_axis( (cpoint - capsule_endpoint_A).normalized() ))
|
if (TEST_POINT(capsule_endpoint_A,cpoint ))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!separator.test_axis( p_transform_inv_b.basis_xform_inv(convex_B->get_segment_normal(i)).normalized() ))
|
if (!separator.test_axis( convex_B->get_xformed_segment_normal(p_transform_b,i)))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -925,26 +1135,31 @@ static void _collision_capsule_convex_polygon(const Shape2DSW* p_a,const Matrix3
|
||||||
/////////
|
/////////
|
||||||
|
|
||||||
|
|
||||||
static void _collision_convex_polygon_convex_polygon(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Matrix32& p_transform_inv_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,const Matrix32& p_transform_inv_b,_CollectorCallback2D *p_collector) {
|
template<bool castA, bool castB>
|
||||||
|
static void _collision_convex_polygon_convex_polygon(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b) {
|
||||||
|
|
||||||
|
|
||||||
const ConvexPolygonShape2DSW *convex_A = static_cast<const ConvexPolygonShape2DSW*>(p_a);
|
const ConvexPolygonShape2DSW *convex_A = static_cast<const ConvexPolygonShape2DSW*>(p_a);
|
||||||
const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW*>(p_b);
|
const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW*>(p_b);
|
||||||
|
|
||||||
SeparatorAxisTest2D<ConvexPolygonShape2DSW,ConvexPolygonShape2DSW> separator(convex_A,p_transform_a,p_transform_inv_a,convex_B,p_transform_b,p_transform_inv_b,p_collector);
|
SeparatorAxisTest2D<ConvexPolygonShape2DSW,ConvexPolygonShape2DSW,castA,castB> separator(convex_A,p_transform_a,convex_B,p_transform_b,p_collector,p_motion_a,p_motion_b);
|
||||||
|
|
||||||
if (!separator.test_previous_axis())
|
if (!separator.test_previous_axis())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!separator.test_cast())
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
for(int i=0;i<convex_A->get_point_count();i++) {
|
for(int i=0;i<convex_A->get_point_count();i++) {
|
||||||
|
|
||||||
if (!separator.test_axis( p_transform_inv_a.basis_xform_inv(convex_A->get_segment_normal(i)).normalized() ))
|
if (!separator.test_axis( convex_A->get_xformed_segment_normal(p_transform_a,i)))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i=0;i<convex_B->get_point_count();i++) {
|
for(int i=0;i<convex_B->get_point_count();i++) {
|
||||||
|
|
||||||
if (!separator.test_axis( p_transform_inv_b.basis_xform_inv(convex_B->get_segment_normal(i)).normalized() ))
|
if (!separator.test_axis( convex_B->get_xformed_segment_normal(p_transform_b,i)))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -955,7 +1170,7 @@ static void _collision_convex_polygon_convex_polygon(const Shape2DSW* p_a,const
|
||||||
|
|
||||||
////////
|
////////
|
||||||
|
|
||||||
bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Matrix32& p_transform_A, const Matrix32& p_transform_inv_A, const Shape2DSW *p_shape_B, const Matrix32& p_transform_B, const Matrix32& p_transform_inv_B, CollisionSolver2DSW::CallbackResult p_result_callback,void *p_userdata, bool p_swap,Vector2 *sep_axis) {
|
bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Matrix32& p_transform_A, const Vector2& p_motion_A, const Shape2DSW *p_shape_B, const Matrix32& p_transform_B,const Vector2& p_motion_B, CollisionSolver2DSW::CallbackResult p_result_callback,void *p_userdata, bool p_swap,Vector2 *sep_axis) {
|
||||||
|
|
||||||
Physics2DServer::ShapeType type_A=p_shape_A->get_type();
|
Physics2DServer::ShapeType type_A=p_shape_A->get_type();
|
||||||
|
|
||||||
|
@ -971,31 +1186,118 @@ bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Matrix32& p_
|
||||||
|
|
||||||
|
|
||||||
static const CollisionFunc collision_table[5][5]={
|
static const CollisionFunc collision_table[5][5]={
|
||||||
{_collision_segment_segment,
|
{_collision_segment_segment<false,false>,
|
||||||
_collision_segment_circle,
|
_collision_segment_circle<false,false>,
|
||||||
_collision_segment_rectangle,
|
_collision_segment_rectangle<false,false>,
|
||||||
_collision_segment_capsule,
|
_collision_segment_capsule<false,false>,
|
||||||
_collision_segment_convex_polygon},
|
_collision_segment_convex_polygon<false,false>},
|
||||||
{0,
|
{0,
|
||||||
_collision_circle_circle,
|
_collision_circle_circle<false,false>,
|
||||||
_collision_circle_rectangle,
|
_collision_circle_rectangle<false,false>,
|
||||||
_collision_circle_capsule,
|
_collision_circle_capsule<false,false>,
|
||||||
_collision_circle_convex_polygon},
|
_collision_circle_convex_polygon<false,false>},
|
||||||
{0,
|
{0,
|
||||||
0,
|
0,
|
||||||
_collision_rectangle_rectangle,
|
_collision_rectangle_rectangle<false,false>,
|
||||||
_collision_rectangle_capsule,
|
_collision_rectangle_capsule<false,false>,
|
||||||
_collision_rectangle_convex_polygon},
|
_collision_rectangle_convex_polygon<false,false>},
|
||||||
{0,
|
{0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
_collision_capsule_capsule,
|
_collision_capsule_capsule<false,false>,
|
||||||
_collision_capsule_convex_polygon},
|
_collision_capsule_convex_polygon<false,false>},
|
||||||
{0,
|
{0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
_collision_convex_polygon_convex_polygon}
|
_collision_convex_polygon_convex_polygon<false,false>}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
static const CollisionFunc collision_table_castA[5][5]={
|
||||||
|
{_collision_segment_segment<true,false>,
|
||||||
|
_collision_segment_circle<true,false>,
|
||||||
|
_collision_segment_rectangle<true,false>,
|
||||||
|
_collision_segment_capsule<true,false>,
|
||||||
|
_collision_segment_convex_polygon<true,false>},
|
||||||
|
{0,
|
||||||
|
_collision_circle_circle<true,false>,
|
||||||
|
_collision_circle_rectangle<true,false>,
|
||||||
|
_collision_circle_capsule<true,false>,
|
||||||
|
_collision_circle_convex_polygon<true,false>},
|
||||||
|
{0,
|
||||||
|
0,
|
||||||
|
_collision_rectangle_rectangle<true,false>,
|
||||||
|
_collision_rectangle_capsule<true,false>,
|
||||||
|
_collision_rectangle_convex_polygon<true,false>},
|
||||||
|
{0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
_collision_capsule_capsule<true,false>,
|
||||||
|
_collision_capsule_convex_polygon<true,false>},
|
||||||
|
{0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
_collision_convex_polygon_convex_polygon<true,false>}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
static const CollisionFunc collision_table_castB[5][5]={
|
||||||
|
{_collision_segment_segment<false,true>,
|
||||||
|
_collision_segment_circle<false,true>,
|
||||||
|
_collision_segment_rectangle<false,true>,
|
||||||
|
_collision_segment_capsule<false,true>,
|
||||||
|
_collision_segment_convex_polygon<false,true>},
|
||||||
|
{0,
|
||||||
|
_collision_circle_circle<false,true>,
|
||||||
|
_collision_circle_rectangle<false,true>,
|
||||||
|
_collision_circle_capsule<false,true>,
|
||||||
|
_collision_circle_convex_polygon<false,true>},
|
||||||
|
{0,
|
||||||
|
0,
|
||||||
|
_collision_rectangle_rectangle<false,true>,
|
||||||
|
_collision_rectangle_capsule<false,true>,
|
||||||
|
_collision_rectangle_convex_polygon<false,true>},
|
||||||
|
{0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
_collision_capsule_capsule<false,true>,
|
||||||
|
_collision_capsule_convex_polygon<false,true>},
|
||||||
|
{0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
_collision_convex_polygon_convex_polygon<false,true>}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
static const CollisionFunc collision_table_castA_castB[5][5]={
|
||||||
|
{_collision_segment_segment<true,true>,
|
||||||
|
_collision_segment_circle<true,true>,
|
||||||
|
_collision_segment_rectangle<true,true>,
|
||||||
|
_collision_segment_capsule<true,true>,
|
||||||
|
_collision_segment_convex_polygon<true,true>},
|
||||||
|
{0,
|
||||||
|
_collision_circle_circle<true,true>,
|
||||||
|
_collision_circle_rectangle<true,true>,
|
||||||
|
_collision_circle_capsule<true,true>,
|
||||||
|
_collision_circle_convex_polygon<true,true>},
|
||||||
|
{0,
|
||||||
|
0,
|
||||||
|
_collision_rectangle_rectangle<true,true>,
|
||||||
|
_collision_rectangle_capsule<true,true>,
|
||||||
|
_collision_rectangle_convex_polygon<true,true>},
|
||||||
|
{0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
_collision_capsule_capsule<true,true>,
|
||||||
|
_collision_capsule_convex_polygon<true,true>},
|
||||||
|
{0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
_collision_convex_polygon_convex_polygon<true,true>}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1010,23 +1312,34 @@ bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Matrix32& p_
|
||||||
const Shape2DSW *B=p_shape_B;
|
const Shape2DSW *B=p_shape_B;
|
||||||
const Matrix32 *transform_A=&p_transform_A;
|
const Matrix32 *transform_A=&p_transform_A;
|
||||||
const Matrix32 *transform_B=&p_transform_B;
|
const Matrix32 *transform_B=&p_transform_B;
|
||||||
const Matrix32 *transform_inv_A=&p_transform_inv_A;
|
const Vector2 *motion_A=&p_motion_A;
|
||||||
const Matrix32 *transform_inv_B=&p_transform_inv_B;
|
const Vector2 *motion_B=&p_motion_B;
|
||||||
|
|
||||||
if (type_A > type_B) {
|
if (type_A > type_B) {
|
||||||
SWAP(A,B);
|
SWAP(A,B);
|
||||||
SWAP(transform_A,transform_B);
|
SWAP(transform_A,transform_B);
|
||||||
SWAP(transform_inv_A,transform_inv_B);
|
|
||||||
SWAP(type_A,type_B);
|
SWAP(type_A,type_B);
|
||||||
|
SWAP(motion_A,motion_B);
|
||||||
callback.swap = !callback.swap;
|
callback.swap = !callback.swap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CollisionFunc collision_func = collision_table[type_A-2][type_B-2];
|
CollisionFunc collision_func;
|
||||||
|
if (*motion_A==Vector2() && *motion_B==Vector2()) {
|
||||||
|
collision_func = collision_table[type_A-2][type_B-2];
|
||||||
|
} else if (*motion_A!=Vector2() && *motion_B==Vector2()) {
|
||||||
|
collision_func = collision_table_castA[type_A-2][type_B-2];
|
||||||
|
} else if (*motion_A==Vector2() && *motion_B!=Vector2()) {
|
||||||
|
collision_func = collision_table_castB[type_A-2][type_B-2];
|
||||||
|
} else {
|
||||||
|
collision_func = collision_table_castA_castB[type_A-2][type_B-2];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ERR_FAIL_COND_V(!collision_func,false);
|
ERR_FAIL_COND_V(!collision_func,false);
|
||||||
|
|
||||||
|
collision_func(A,*transform_A,B,*transform_B,&callback,*motion_A,*motion_B);
|
||||||
collision_func(A,*transform_A,*transform_inv_A,B,*transform_B,*transform_inv_B,&callback);
|
|
||||||
|
|
||||||
return callback.collided;
|
return callback.collided;
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,6 @@
|
||||||
#include "collision_solver_2d_sw.h"
|
#include "collision_solver_2d_sw.h"
|
||||||
|
|
||||||
|
|
||||||
bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Matrix32& p_transform_A, const Matrix32& p_transform_inv_A, const Shape2DSW *p_shape_B, const Matrix32& p_transform_B, const Matrix32& p_transform_inv_B, CollisionSolver2DSW::CallbackResult p_result_callback,void *p_userdata, bool p_swap=false,Vector2 *sep_axis=NULL);
|
bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Matrix32& p_transform_A, const Vector2& p_motion_A,const Shape2DSW *p_shape_B, const Matrix32& p_transform_B,const Vector2& p_motion_B, CollisionSolver2DSW::CallbackResult p_result_callback,void *p_userdata, bool p_swap=false,Vector2 *sep_axis=NULL);
|
||||||
|
|
||||||
#endif // COLLISION_SOLVER_2D_SAT_H
|
#endif // COLLISION_SOLVER_2D_SAT_H
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
//#define collision_solver gjk_epa_calculate_penetration
|
//#define collision_solver gjk_epa_calculate_penetration
|
||||||
|
|
||||||
|
|
||||||
bool CollisionSolver2DSW::solve_static_line(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Matrix32& p_transform_inv_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,const Matrix32& p_transform_inv_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result) {
|
bool CollisionSolver2DSW::solve_static_line(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result) {
|
||||||
|
|
||||||
|
|
||||||
const LineShape2DSW *line = static_cast<const LineShape2DSW*>(p_shape_A);
|
const LineShape2DSW *line = static_cast<const LineShape2DSW*>(p_shape_A);
|
||||||
|
@ -49,7 +49,7 @@ bool CollisionSolver2DSW::solve_static_line(const Shape2DSW *p_shape_A,const Mat
|
||||||
Vector2 supports[2];
|
Vector2 supports[2];
|
||||||
int support_count;
|
int support_count;
|
||||||
|
|
||||||
p_shape_B->get_supports(p_transform_inv_B.basis_xform(-n).normalized(),supports,support_count);
|
p_shape_B->get_supports(p_transform_A.affine_inverse().basis_xform(-n).normalized(),supports,support_count);
|
||||||
|
|
||||||
bool found=false;
|
bool found=false;
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ bool CollisionSolver2DSW::solve_static_line(const Shape2DSW *p_shape_A,const Mat
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CollisionSolver2DSW::solve_raycast(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Matrix32& p_transform_inv_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,const Matrix32& p_transform_inv_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis) {
|
bool CollisionSolver2DSW::solve_raycast(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -89,8 +89,9 @@ bool CollisionSolver2DSW::solve_raycast(const Shape2DSW *p_shape_A,const Matrix3
|
||||||
Vector2 to = from+p_transform_A[1]*ray->get_length();
|
Vector2 to = from+p_transform_A[1]*ray->get_length();
|
||||||
Vector2 support_A=to;
|
Vector2 support_A=to;
|
||||||
|
|
||||||
from = p_transform_inv_B.xform(from);
|
Matrix32 invb = p_transform_B.affine_inverse();
|
||||||
to = p_transform_inv_B.xform(to);
|
from = invb.xform(from);
|
||||||
|
to = invb.xform(to);
|
||||||
|
|
||||||
Vector2 p,n;
|
Vector2 p,n;
|
||||||
if (!p_shape_B->intersect_segment(from,to,p,n)) {
|
if (!p_shape_B->intersect_segment(from,to,p,n)) {
|
||||||
|
@ -145,10 +146,10 @@ bool CollisionSolver2DSW::solve_ray(const Shape2DSW *p_shape_A,const Matrix32& p
|
||||||
struct _ConcaveCollisionInfo2D {
|
struct _ConcaveCollisionInfo2D {
|
||||||
|
|
||||||
const Matrix32 *transform_A;
|
const Matrix32 *transform_A;
|
||||||
const Matrix32 *transform_inv_A;
|
|
||||||
const Shape2DSW *shape_A;
|
const Shape2DSW *shape_A;
|
||||||
const Matrix32 *transform_B;
|
const Matrix32 *transform_B;
|
||||||
const Matrix32 *transform_inv_B;
|
Vector2 motion_A;
|
||||||
|
Vector2 motion_B;
|
||||||
CollisionSolver2DSW::CallbackResult result_callback;
|
CollisionSolver2DSW::CallbackResult result_callback;
|
||||||
void *userdata;
|
void *userdata;
|
||||||
bool swap_result;
|
bool swap_result;
|
||||||
|
@ -168,7 +169,7 @@ void CollisionSolver2DSW::concave_callback(void *p_userdata, Shape2DSW *p_convex
|
||||||
if (!cinfo.result_callback && cinfo.collided)
|
if (!cinfo.result_callback && cinfo.collided)
|
||||||
return; //already collided and no contacts requested, don't test anymore
|
return; //already collided and no contacts requested, don't test anymore
|
||||||
|
|
||||||
bool collided = collision_solver(cinfo.shape_A, *cinfo.transform_A, *cinfo.transform_inv_A, p_convex,*cinfo.transform_B,*cinfo.transform_inv_B, cinfo.result_callback, cinfo.userdata, cinfo.swap_result,cinfo.sep_axis );
|
bool collided = collision_solver(cinfo.shape_A, *cinfo.transform_A, cinfo.motion_A, p_convex,*cinfo.transform_B, cinfo.motion_B, cinfo.result_callback, cinfo.userdata, cinfo.swap_result,cinfo.sep_axis );
|
||||||
if (!collided)
|
if (!collided)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -178,17 +179,16 @@ void CollisionSolver2DSW::concave_callback(void *p_userdata, Shape2DSW *p_convex
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Matrix32& p_transform_inv_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,const Matrix32& p_transform_inv_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis) {
|
bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis) {
|
||||||
|
|
||||||
|
|
||||||
const ConcaveShape2DSW *concave_B=static_cast<const ConcaveShape2DSW*>(p_shape_B);
|
const ConcaveShape2DSW *concave_B=static_cast<const ConcaveShape2DSW*>(p_shape_B);
|
||||||
|
|
||||||
_ConcaveCollisionInfo2D cinfo;
|
_ConcaveCollisionInfo2D cinfo;
|
||||||
cinfo.transform_A=&p_transform_A;
|
cinfo.transform_A=&p_transform_A;
|
||||||
cinfo.transform_inv_A=&p_transform_inv_A;
|
|
||||||
cinfo.shape_A=p_shape_A;
|
cinfo.shape_A=p_shape_A;
|
||||||
cinfo.transform_B=&p_transform_B;
|
cinfo.transform_B=&p_transform_B;
|
||||||
cinfo.transform_inv_B=&p_transform_inv_B;
|
cinfo.motion_A=p_motion_A;
|
||||||
cinfo.result_callback=p_result_callback;
|
cinfo.result_callback=p_result_callback;
|
||||||
cinfo.userdata=p_userdata;
|
cinfo.userdata=p_userdata;
|
||||||
cinfo.swap_result=p_swap_result;
|
cinfo.swap_result=p_swap_result;
|
||||||
|
@ -227,7 +227,8 @@ bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A,const Matrix3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CollisionSolver2DSW::solve_static(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Matrix32& p_transform_inv_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,const Matrix32& p_transform_inv_B,CallbackResult p_result_callback,void *p_userdata,Vector2 *sep_axis) {
|
bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,Vector2 *sep_axis) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -253,9 +254,9 @@ bool CollisionSolver2DSW::solve_static(const Shape2DSW *p_shape_A,const Matrix32
|
||||||
}
|
}
|
||||||
|
|
||||||
if (swap) {
|
if (swap) {
|
||||||
return solve_static_line(p_shape_B,p_transform_B,p_transform_inv_B,p_shape_A,p_transform_A,p_transform_inv_A,p_result_callback,p_userdata,true);
|
return solve_static_line(p_shape_B,p_transform_B,p_shape_A,p_transform_A,p_result_callback,p_userdata,true);
|
||||||
} else {
|
} else {
|
||||||
return solve_static_line(p_shape_A,p_transform_A,p_transform_inv_A,p_shape_B,p_transform_B,p_transform_inv_B,p_result_callback,p_userdata,false);
|
return solve_static_line(p_shape_A,p_transform_A,p_shape_B,p_transform_B,p_result_callback,p_userdata,false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*} else if (type_A==Physics2DServer::SHAPE_RAY) {
|
/*} else if (type_A==Physics2DServer::SHAPE_RAY) {
|
||||||
|
@ -278,9 +279,9 @@ bool CollisionSolver2DSW::solve_static(const Shape2DSW *p_shape_A,const Matrix32
|
||||||
|
|
||||||
|
|
||||||
if (swap) {
|
if (swap) {
|
||||||
return solve_raycast(p_shape_B,p_transform_B,p_transform_inv_B,p_shape_A,p_transform_A,p_transform_inv_A,p_result_callback,p_userdata,true,sep_axis);
|
return solve_raycast(p_shape_B,p_transform_B,p_shape_A,p_transform_A,p_result_callback,p_userdata,true,sep_axis);
|
||||||
} else {
|
} else {
|
||||||
return solve_raycast(p_shape_A,p_transform_A,p_transform_inv_A,p_shape_B,p_transform_B,p_transform_inv_B,p_result_callback,p_userdata,false,sep_axis);
|
return solve_raycast(p_shape_A,p_transform_A,p_shape_B,p_transform_B,p_result_callback,p_userdata,false,sep_axis);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -291,16 +292,16 @@ bool CollisionSolver2DSW::solve_static(const Shape2DSW *p_shape_A,const Matrix32
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!swap)
|
if (!swap)
|
||||||
return solve_concave(p_shape_A,p_transform_A,p_transform_inv_A,p_shape_B,p_transform_B,p_transform_inv_B,p_result_callback,p_userdata,false,sep_axis);
|
return solve_concave(p_shape_A,p_transform_A,p_motion_A,p_shape_B,p_transform_B,p_motion_B,p_result_callback,p_userdata,false,sep_axis);
|
||||||
else
|
else
|
||||||
return solve_concave(p_shape_B,p_transform_B,p_transform_inv_B,p_shape_A,p_transform_A,p_transform_inv_A,p_result_callback,p_userdata,true,sep_axis);
|
return solve_concave(p_shape_B,p_transform_B,p_motion_B,p_shape_A,p_transform_A,p_motion_A,p_result_callback,p_userdata,true,sep_axis);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|
||||||
return collision_solver(p_shape_A, p_transform_A, p_transform_inv_A, p_shape_B, p_transform_B, p_transform_inv_B, p_result_callback,p_userdata,false,sep_axis);
|
return collision_solver(p_shape_A, p_transform_A,p_motion_A, p_shape_B, p_transform_B, p_motion_B,p_result_callback,p_userdata,false,sep_axis);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -35,16 +35,16 @@ class CollisionSolver2DSW {
|
||||||
public:
|
public:
|
||||||
typedef void (*CallbackResult)(const Vector2& p_point_A,const Vector2& p_point_B,void *p_userdata);
|
typedef void (*CallbackResult)(const Vector2& p_point_A,const Vector2& p_point_B,void *p_userdata);
|
||||||
private:
|
private:
|
||||||
static bool solve_static_line(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Matrix32& p_transform_inv_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,const Matrix32& p_transform_inv_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result);
|
static bool solve_static_line(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result);
|
||||||
static void concave_callback(void *p_userdata, Shape2DSW *p_convex);
|
static void concave_callback(void *p_userdata, Shape2DSW *p_convex);
|
||||||
static bool solve_concave(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Matrix32& p_transform_inv_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,const Matrix32& p_transform_inv_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis=NULL);
|
static bool solve_concave(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis=NULL);
|
||||||
static bool solve_raycast(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Matrix32& p_transform_inv_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,const Matrix32& p_transform_inv_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis=NULL);
|
static bool solve_raycast(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis=NULL);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static bool solve_static(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Matrix32& p_inverse_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,const Matrix32& p_inverse_B,CallbackResult p_result_callback,void *p_userdata,Vector2 *sep_axis=NULL);
|
static bool solve(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,Vector2 *sep_axis=NULL);
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "physics_2d_server_sw.h"
|
#include "physics_2d_server_sw.h"
|
||||||
#include "broad_phase_2d_basic.h"
|
#include "broad_phase_2d_basic.h"
|
||||||
#include "broad_phase_2d_hash_grid.h"
|
#include "broad_phase_2d_hash_grid.h"
|
||||||
|
#include "collision_solver_2d_sw.h"
|
||||||
|
|
||||||
RID Physics2DServerSW::shape_create(ShapeType p_shape) {
|
RID Physics2DServerSW::shape_create(ShapeType p_shape) {
|
||||||
|
|
||||||
|
@ -81,6 +82,9 @@ RID Physics2DServerSW::shape_create(ShapeType p_shape) {
|
||||||
return id;
|
return id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Physics2DServerSW::shape_set_data(RID p_shape, const Variant& p_data) {
|
void Physics2DServerSW::shape_set_data(RID p_shape, const Variant& p_data) {
|
||||||
|
|
||||||
Shape2DSW *shape = shape_owner.get(p_shape);
|
Shape2DSW *shape = shape_owner.get(p_shape);
|
||||||
|
@ -126,6 +130,63 @@ real_t Physics2DServerSW::shape_get_custom_solver_bias(RID p_shape) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Physics2DServerSW::_shape_col_cbk(const Vector2& p_point_A,const Vector2& p_point_B,void *p_userdata) {
|
||||||
|
|
||||||
|
CollCbkData *cbk=(CollCbkData *)p_userdata;
|
||||||
|
|
||||||
|
if (cbk->amount == cbk->max) {
|
||||||
|
//find least deep
|
||||||
|
float min_depth=1e20;
|
||||||
|
int min_depth_idx=0;
|
||||||
|
for(int i=0;i<cbk->amount;i++) {
|
||||||
|
|
||||||
|
float d = cbk->ptr[i*2+0].distance_squared_to(cbk->ptr[i*2+1]);
|
||||||
|
if (d<min_depth) {
|
||||||
|
min_depth=d;
|
||||||
|
min_depth_idx=i;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
float d = p_point_A.distance_squared_to(p_point_B);
|
||||||
|
if (d<min_depth)
|
||||||
|
return;
|
||||||
|
cbk->ptr[min_depth_idx*2+0]=p_point_A;
|
||||||
|
cbk->ptr[min_depth_idx*2+1]=p_point_B;
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
cbk->ptr[cbk->amount*2+0]=p_point_A;
|
||||||
|
cbk->ptr[cbk->amount*2+1]=p_point_B;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Physics2DServerSW::shape_collide(RID p_shape_A, const Matrix32& p_xform_A,const Vector2& p_motion_A,RID p_shape_B, const Matrix32& p_xform_B, const Vector2& p_motion_B,Vector2 *r_results,int p_result_max,int &r_result_count) {
|
||||||
|
|
||||||
|
|
||||||
|
Shape2DSW *shape_A = shape_owner.get(p_shape_A);
|
||||||
|
ERR_FAIL_COND_V(!shape_A,false);
|
||||||
|
Shape2DSW *shape_B = shape_owner.get(p_shape_B);
|
||||||
|
ERR_FAIL_COND_V(!shape_B,false);
|
||||||
|
|
||||||
|
if (p_result_max==0) {
|
||||||
|
|
||||||
|
return CollisionSolver2DSW::solve(shape_A,p_xform_A,p_motion_A,shape_B,p_xform_B,p_motion_B,NULL,NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
CollCbkData cbk;
|
||||||
|
cbk.max=p_result_max;
|
||||||
|
cbk.amount=0;
|
||||||
|
cbk.ptr=r_results;
|
||||||
|
|
||||||
|
bool res= CollisionSolver2DSW::solve(shape_A,p_xform_A,p_motion_A,shape_B,p_xform_B,p_motion_B,_shape_col_cbk,&cbk);
|
||||||
|
r_result_count=cbk.amount;
|
||||||
|
return res;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
RID Physics2DServerSW::space_create() {
|
RID Physics2DServerSW::space_create() {
|
||||||
|
|
||||||
Space2DSW *space = memnew( Space2DSW );
|
Space2DSW *space = memnew( Space2DSW );
|
||||||
|
@ -442,7 +503,7 @@ void Physics2DServerSW::body_set_mode(RID p_body, BodyMode p_mode) {
|
||||||
body->set_mode(p_mode);
|
body->set_mode(p_mode);
|
||||||
};
|
};
|
||||||
|
|
||||||
Physics2DServer::BodyMode Physics2DServerSW::body_get_mode(RID p_body, BodyMode p_mode) const {
|
Physics2DServer::BodyMode Physics2DServerSW::body_get_mode(RID p_body) const {
|
||||||
|
|
||||||
Body2DSW *body = body_owner.get(p_body);
|
Body2DSW *body = body_owner.get(p_body);
|
||||||
ERR_FAIL_COND_V(!body,BODY_MODE_STATIC);
|
ERR_FAIL_COND_V(!body,BODY_MODE_STATIC);
|
||||||
|
@ -550,23 +611,25 @@ bool Physics2DServerSW::body_is_shape_set_as_trigger(RID p_body, int p_shape_idx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Physics2DServerSW::body_set_enable_continuous_collision_detection(RID p_body,bool p_enable) {
|
void Physics2DServerSW::body_set_continuous_collision_detection_mode(RID p_body,CCDMode p_mode) {
|
||||||
|
|
||||||
Body2DSW *body = body_owner.get(p_body);
|
Body2DSW *body = body_owner.get(p_body);
|
||||||
ERR_FAIL_COND(!body);
|
ERR_FAIL_COND(!body);
|
||||||
|
body->set_continuous_collision_detection_mode(p_mode);
|
||||||
body->set_continuous_collision_detection(p_enable);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Physics2DServerSW::body_is_continuous_collision_detection_enabled(RID p_body) const {
|
Physics2DServerSW::CCDMode Physics2DServerSW::body_get_continuous_collision_detection_mode(RID p_body) const{
|
||||||
|
|
||||||
Body2DSW *body = body_owner.get(p_body);
|
const Body2DSW *body = body_owner.get(p_body);
|
||||||
ERR_FAIL_COND_V(!body,false);
|
ERR_FAIL_COND_V(!body,CCD_MODE_DISABLED);
|
||||||
|
|
||||||
|
return body->get_continuous_collision_detection_mode();
|
||||||
|
|
||||||
return body->is_continuous_collision_detection_enabled();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Physics2DServerSW::body_attach_object_instance_ID(RID p_body,uint32_t p_ID) {
|
void Physics2DServerSW::body_attach_object_instance_ID(RID p_body,uint32_t p_ID) {
|
||||||
|
|
||||||
Body2DSW *body = body_owner.get(p_body);
|
Body2DSW *body = body_owner.get(p_body);
|
||||||
|
@ -617,13 +680,6 @@ float Physics2DServerSW::body_get_param(RID p_body, BodyParameter p_param) const
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void Physics2DServerSW::body_static_simulate_motion(RID p_body,const Matrix32& p_new_transform) {
|
|
||||||
|
|
||||||
Body2DSW *body = body_owner.get(p_body);
|
|
||||||
ERR_FAIL_COND(!body);
|
|
||||||
body->simulate_motion(p_new_transform,last_step);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
void Physics2DServerSW::body_set_state(RID p_body, BodyState p_state, const Variant& p_variant) {
|
void Physics2DServerSW::body_set_state(RID p_body, BodyState p_state, const Variant& p_variant) {
|
||||||
|
|
||||||
|
@ -775,6 +831,16 @@ void Physics2DServerSW::body_set_force_integration_callback(RID p_body,Object *p
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Physics2DServerSW::body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count) {
|
||||||
|
|
||||||
|
Body2DSW *body = body_owner.get(p_body);
|
||||||
|
ERR_FAIL_COND_V(!body,false);
|
||||||
|
ERR_FAIL_INDEX_V(p_body_shape,body->get_shape_count(),false);
|
||||||
|
|
||||||
|
return shape_collide(body->get_shape(p_body_shape)->get_self(),body->get_transform() * body->get_shape_transform(p_body_shape),Vector2(),p_shape,p_shape_xform,p_motion,r_results,p_result_max,r_result_count);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* JOINT API */
|
/* JOINT API */
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,16 @@ friend class Physics2DDirectSpaceStateSW;
|
||||||
mutable RID_Owner<Body2DSW> body_owner;
|
mutable RID_Owner<Body2DSW> body_owner;
|
||||||
mutable RID_Owner<Joint2DSW> joint_owner;
|
mutable RID_Owner<Joint2DSW> joint_owner;
|
||||||
|
|
||||||
|
struct CollCbkData {
|
||||||
|
|
||||||
|
int max;
|
||||||
|
int amount;
|
||||||
|
Vector2 *ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void _shape_col_cbk(const Vector2& p_point_A,const Vector2& p_point_B,void *p_userdata);
|
||||||
|
|
||||||
|
|
||||||
// void _clear_query(Query2DSW *p_query);
|
// void _clear_query(Query2DSW *p_query);
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -69,6 +79,8 @@ public:
|
||||||
virtual Variant shape_get_data(RID p_shape) const;
|
virtual Variant shape_get_data(RID p_shape) const;
|
||||||
virtual real_t shape_get_custom_solver_bias(RID p_shape) const;
|
virtual real_t shape_get_custom_solver_bias(RID p_shape) const;
|
||||||
|
|
||||||
|
virtual bool shape_collide(RID p_shape_A, const Matrix32& p_xform_A,const Vector2& p_motion_A,RID p_shape_B, const Matrix32& p_xform_B, const Vector2& p_motion_B,Vector2 *r_results,int p_result_max,int &r_result_count);
|
||||||
|
|
||||||
/* SPACE API */
|
/* SPACE API */
|
||||||
|
|
||||||
virtual RID space_create();
|
virtual RID space_create();
|
||||||
|
@ -124,7 +136,7 @@ public:
|
||||||
virtual RID body_get_space(RID p_body) const;
|
virtual RID body_get_space(RID p_body) const;
|
||||||
|
|
||||||
virtual void body_set_mode(RID p_body, BodyMode p_mode);
|
virtual void body_set_mode(RID p_body, BodyMode p_mode);
|
||||||
virtual BodyMode body_get_mode(RID p_body, BodyMode p_mode) const;
|
virtual BodyMode body_get_mode(RID p_body) const;
|
||||||
|
|
||||||
virtual void body_add_shape(RID p_body, RID p_shape, const Matrix32& p_transform=Matrix32());
|
virtual void body_add_shape(RID p_body, RID p_shape, const Matrix32& p_transform=Matrix32());
|
||||||
virtual void body_set_shape(RID p_body, int p_shape_idx,RID p_shape);
|
virtual void body_set_shape(RID p_body, int p_shape_idx,RID p_shape);
|
||||||
|
@ -143,8 +155,8 @@ public:
|
||||||
virtual void body_attach_object_instance_ID(RID p_body,uint32_t p_ID);
|
virtual void body_attach_object_instance_ID(RID p_body,uint32_t p_ID);
|
||||||
virtual uint32_t body_get_object_instance_ID(RID p_body) const;
|
virtual uint32_t body_get_object_instance_ID(RID p_body) const;
|
||||||
|
|
||||||
virtual void body_set_enable_continuous_collision_detection(RID p_body,bool p_enable);
|
virtual void body_set_continuous_collision_detection_mode(RID p_body,CCDMode p_mode);
|
||||||
virtual bool body_is_continuous_collision_detection_enabled(RID p_body) const;
|
virtual CCDMode body_get_continuous_collision_detection_mode(RID p_body) const;
|
||||||
|
|
||||||
virtual void body_set_user_flags(RID p_body, uint32_t p_flags);
|
virtual void body_set_user_flags(RID p_body, uint32_t p_flags);
|
||||||
virtual uint32_t body_get_user_flags(RID p_body, uint32_t p_flags) const;
|
virtual uint32_t body_get_user_flags(RID p_body, uint32_t p_flags) const;
|
||||||
|
@ -152,8 +164,6 @@ public:
|
||||||
virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value);
|
virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value);
|
||||||
virtual float body_get_param(RID p_body, BodyParameter p_param) const;
|
virtual float body_get_param(RID p_body, BodyParameter p_param) const;
|
||||||
|
|
||||||
//advanced simulation
|
|
||||||
virtual void body_static_simulate_motion(RID p_body,const Matrix32& p_new_transform);
|
|
||||||
|
|
||||||
virtual void body_set_state(RID p_body, BodyState p_state, const Variant& p_variant);
|
virtual void body_set_state(RID p_body, BodyState p_state, const Variant& p_variant);
|
||||||
virtual Variant body_get_state(RID p_body, BodyState p_state) const;
|
virtual Variant body_get_state(RID p_body, BodyState p_state) const;
|
||||||
|
@ -181,6 +191,7 @@ public:
|
||||||
virtual int body_get_max_contacts_reported(RID p_body) const;
|
virtual int body_get_max_contacts_reported(RID p_body) const;
|
||||||
|
|
||||||
virtual void body_set_force_integration_callback(RID p_body,Object *p_receiver,const StringName& p_method,const Variant& p_udata=Variant());
|
virtual void body_set_force_integration_callback(RID p_body,Object *p_receiver,const StringName& p_method,const Variant& p_udata=Variant());
|
||||||
|
virtual bool body_collide_shape(RID p_body, int p_body_shape,RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count);
|
||||||
|
|
||||||
/* JOINT API */
|
/* JOINT API */
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -26,417 +26,516 @@
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
#ifndef SHAPE_2D_2DSW_H
|
#ifndef SHAPE_2D_2DSW_H
|
||||||
#define SHAPE_2D_2DSW_H
|
#define SHAPE_2D_2DSW_H
|
||||||
|
|
||||||
#include "servers/physics_2d_server.h"
|
#include "servers/physics_2d_server.h"
|
||||||
/*
|
#define _SEGMENT_IS_VALID_SUPPORT_TRESHOLD 0.99998
|
||||||
|
|
||||||
SHAPE_LINE, ///< plane:"plane"
|
/*
|
||||||
SHAPE_SEGMENT, ///< float:"length"
|
|
||||||
SHAPE_CIRCLE, ///< float:"radius"
|
SHAPE_LINE, ///< plane:"plane"
|
||||||
SHAPE_RECTANGLE, ///< vec3:"extents"
|
SHAPE_SEGMENT, ///< float:"length"
|
||||||
SHAPE_CONVEX_POLYGON, ///< array of planes:"planes"
|
SHAPE_CIRCLE, ///< float:"radius"
|
||||||
SHAPE_CONCAVE_POLYGON, ///< Vector2 array:"triangles" , or Dictionary with "indices" (int array) and "triangles" (Vector2 array)
|
SHAPE_RECTANGLE, ///< vec3:"extents"
|
||||||
SHAPE_CUSTOM, ///< Server-Implementation based custom shape, calling shape_create() with this value will result in an error
|
SHAPE_CONVEX_POLYGON, ///< array of planes:"planes"
|
||||||
|
SHAPE_CONCAVE_POLYGON, ///< Vector2 array:"triangles" , or Dictionary with "indices" (int array) and "triangles" (Vector2 array)
|
||||||
*/
|
SHAPE_CUSTOM, ///< Server-Implementation based custom shape, calling shape_create() with this value will result in an error
|
||||||
|
|
||||||
class Shape2DSW;
|
*/
|
||||||
|
|
||||||
class ShapeOwner2DSW {
|
class Shape2DSW;
|
||||||
public:
|
|
||||||
|
class ShapeOwner2DSW {
|
||||||
virtual void _shape_changed()=0;
|
public:
|
||||||
virtual void remove_shape(Shape2DSW *p_shape)=0;
|
|
||||||
|
virtual void _shape_changed()=0;
|
||||||
virtual ~ShapeOwner2DSW() {}
|
virtual void remove_shape(Shape2DSW *p_shape)=0;
|
||||||
};
|
|
||||||
|
virtual ~ShapeOwner2DSW() {}
|
||||||
class Shape2DSW {
|
};
|
||||||
|
|
||||||
RID self;
|
class Shape2DSW {
|
||||||
Rect2 aabb;
|
|
||||||
bool configured;
|
RID self;
|
||||||
real_t custom_bias;
|
Rect2 aabb;
|
||||||
|
bool configured;
|
||||||
Map<ShapeOwner2DSW*,int> owners;
|
real_t custom_bias;
|
||||||
protected:
|
|
||||||
|
Map<ShapeOwner2DSW*,int> owners;
|
||||||
void configure(const Rect2& p_aabb);
|
protected:
|
||||||
public:
|
|
||||||
|
void configure(const Rect2& p_aabb);
|
||||||
_FORCE_INLINE_ void set_self(const RID& p_self) { self=p_self; }
|
public:
|
||||||
_FORCE_INLINE_ RID get_self() const {return self; }
|
|
||||||
|
_FORCE_INLINE_ void set_self(const RID& p_self) { self=p_self; }
|
||||||
virtual Physics2DServer::ShapeType get_type() const=0;
|
_FORCE_INLINE_ RID get_self() const {return self; }
|
||||||
|
|
||||||
_FORCE_INLINE_ Rect2 get_aabb() const { return aabb; }
|
virtual Physics2DServer::ShapeType get_type() const=0;
|
||||||
_FORCE_INLINE_ bool is_configured() const { return configured; }
|
|
||||||
|
_FORCE_INLINE_ Rect2 get_aabb() const { return aabb; }
|
||||||
virtual bool is_concave() const { return false; }
|
_FORCE_INLINE_ bool is_configured() const { return configured; }
|
||||||
|
|
||||||
virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const=0;
|
virtual bool is_concave() const { return false; }
|
||||||
virtual Vector2 get_support(const Vector2& p_normal) const;
|
|
||||||
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const=0;
|
virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const=0;
|
||||||
|
virtual void project_range_castv(const Vector2& p_cast, const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const=0;
|
||||||
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const=0;
|
virtual Vector2 get_support(const Vector2& p_normal) const;
|
||||||
virtual real_t get_moment_of_inertia(float p_mass) const=0;
|
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const=0;
|
||||||
|
|
||||||
virtual void set_data(const Variant& p_data)=0;
|
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const=0;
|
||||||
virtual Variant get_data() const=0;
|
virtual real_t get_moment_of_inertia(float p_mass) const=0;
|
||||||
|
|
||||||
_FORCE_INLINE_ void set_custom_bias(real_t p_bias) { custom_bias=p_bias; }
|
virtual void set_data(const Variant& p_data)=0;
|
||||||
_FORCE_INLINE_ real_t get_custom_bias() const { return custom_bias; }
|
virtual Variant get_data() const=0;
|
||||||
|
|
||||||
void add_owner(ShapeOwner2DSW *p_owner);
|
_FORCE_INLINE_ void set_custom_bias(real_t p_bias) { custom_bias=p_bias; }
|
||||||
void remove_owner(ShapeOwner2DSW *p_owner);
|
_FORCE_INLINE_ real_t get_custom_bias() const { return custom_bias; }
|
||||||
bool is_owner(ShapeOwner2DSW *p_owner) const;
|
|
||||||
const Map<ShapeOwner2DSW*,int>& get_owners() const;
|
void add_owner(ShapeOwner2DSW *p_owner);
|
||||||
|
void remove_owner(ShapeOwner2DSW *p_owner);
|
||||||
Shape2DSW();
|
bool is_owner(ShapeOwner2DSW *p_owner) const;
|
||||||
virtual ~Shape2DSW();
|
const Map<ShapeOwner2DSW*,int>& get_owners() const;
|
||||||
};
|
|
||||||
|
|
||||||
|
_FORCE_INLINE_ void get_supports_transformed_cast(const Vector2& p_cast,const Vector2& p_normal,const Matrix32& p_xform,Vector2 *r_supports,int & r_amount) const {
|
||||||
class LineShape2DSW : public Shape2DSW {
|
|
||||||
|
get_supports(p_xform.basis_xform_inv(p_normal).normalized(),r_supports,r_amount);
|
||||||
|
for(int i=0;i<r_amount;i++)
|
||||||
Vector2 normal;
|
r_supports[i]=p_xform.xform(r_supports[i]);
|
||||||
real_t d;
|
|
||||||
|
if (r_amount==1) {
|
||||||
public:
|
|
||||||
|
if (Math::abs( p_normal.dot(p_cast.normalized()) )<(1.0-_SEGMENT_IS_VALID_SUPPORT_TRESHOLD) ) {
|
||||||
_FORCE_INLINE_ Vector2 get_normal() const { return normal; }
|
//make line because they are parallel
|
||||||
_FORCE_INLINE_ real_t get_d() const { return d; }
|
r_amount=2;
|
||||||
|
r_supports[1]=r_supports[0]+p_cast;
|
||||||
virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_LINE; }
|
} else if (p_cast.dot(p_normal)>0) {
|
||||||
|
//normal points towards cast, add cast
|
||||||
virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
|
r_supports[0]+=p_cast;
|
||||||
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
|
}
|
||||||
|
|
||||||
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
|
} else {
|
||||||
virtual real_t get_moment_of_inertia(float p_mass) const;
|
|
||||||
|
if (Math::abs( p_normal.dot(p_cast.normalized()) )<(1.0-_SEGMENT_IS_VALID_SUPPORT_TRESHOLD) ) {
|
||||||
virtual void set_data(const Variant& p_data);
|
//optimize line and make it larger because they are parallel
|
||||||
virtual Variant get_data() const;
|
if ((r_supports[1]-r_supports[0]).dot(p_cast)>0) {
|
||||||
|
//larger towards 1
|
||||||
_FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
|
r_supports[1]+=p_cast;
|
||||||
//real large
|
} else {
|
||||||
r_min=-1e10;
|
//larger towards 0
|
||||||
r_max=1e10;
|
r_supports[0]+=p_cast;
|
||||||
}
|
}
|
||||||
|
} else if (p_cast.dot(p_normal)>0) {
|
||||||
};
|
//normal points towards cast, add cast
|
||||||
|
r_supports[0]+=p_cast;
|
||||||
|
r_supports[1]+=p_cast;
|
||||||
class RayShape2DSW : public Shape2DSW {
|
}
|
||||||
|
|
||||||
|
}
|
||||||
real_t length;
|
}
|
||||||
|
|
||||||
public:
|
Shape2DSW();
|
||||||
|
virtual ~Shape2DSW();
|
||||||
|
};
|
||||||
_FORCE_INLINE_ real_t get_length() const { return length; }
|
|
||||||
|
//let the optimizer do the magic
|
||||||
virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_RAY; }
|
#define DEFAULT_PROJECT_RANGE_CAST \
|
||||||
|
virtual void project_range_castv(const Vector2& p_cast, const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {\
|
||||||
virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
|
project_range_cast(p_cast,p_normal,p_transform,r_min,r_max);\
|
||||||
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
|
}\
|
||||||
|
_FORCE_INLINE_ void project_range_cast(const Vector2& p_cast, const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {\
|
||||||
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
|
\
|
||||||
virtual real_t get_moment_of_inertia(float p_mass) const;
|
real_t mina,maxa;\
|
||||||
|
real_t minb,maxb;\
|
||||||
virtual void set_data(const Variant& p_data);
|
Matrix32 ofsb=p_transform;\
|
||||||
virtual Variant get_data() const;
|
ofsb.elements[2]+=p_cast;\
|
||||||
|
project_range(p_normal,p_transform,mina,maxa);\
|
||||||
_FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
|
project_range(p_normal,ofsb,minb,maxb); \
|
||||||
//real large
|
r_min=MIN(mina,minb);\
|
||||||
r_max = p_normal.dot(p_transform.get_origin());
|
r_max=MAX(maxa,maxb);\
|
||||||
r_min = p_normal.dot(p_transform.xform(Vector2(0,length)));
|
}
|
||||||
if (r_max<r_min) {
|
|
||||||
|
class LineShape2DSW : public Shape2DSW {
|
||||||
SWAP(r_max,r_min);
|
|
||||||
}
|
|
||||||
}
|
Vector2 normal;
|
||||||
|
real_t d;
|
||||||
_FORCE_INLINE_ RayShape2DSW() {}
|
|
||||||
_FORCE_INLINE_ RayShape2DSW(real_t p_length) { length=p_length; }
|
public:
|
||||||
};
|
|
||||||
|
_FORCE_INLINE_ Vector2 get_normal() const { return normal; }
|
||||||
|
_FORCE_INLINE_ real_t get_d() const { return d; }
|
||||||
class SegmentShape2DSW : public Shape2DSW {
|
|
||||||
|
virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_LINE; }
|
||||||
|
|
||||||
Vector2 a;
|
virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
|
||||||
Vector2 b;
|
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
|
||||||
Vector2 n;
|
|
||||||
|
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
|
||||||
public:
|
virtual real_t get_moment_of_inertia(float p_mass) const;
|
||||||
|
|
||||||
|
virtual void set_data(const Variant& p_data);
|
||||||
_FORCE_INLINE_ const Vector2& get_a() const { return a; }
|
virtual Variant get_data() const;
|
||||||
_FORCE_INLINE_ const Vector2& get_b() const { return b; }
|
|
||||||
_FORCE_INLINE_ const Vector2& get_normal() const { return n; }
|
_FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
|
||||||
|
//real large
|
||||||
virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_SEGMENT; }
|
r_min=-1e10;
|
||||||
|
r_max=1e10;
|
||||||
virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
|
}
|
||||||
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
|
|
||||||
|
virtual void project_range_castv(const Vector2& p_cast, const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
|
||||||
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
|
project_range_cast(p_cast,p_normal,p_transform,r_min,r_max);
|
||||||
virtual real_t get_moment_of_inertia(float p_mass) const;
|
}
|
||||||
|
|
||||||
virtual void set_data(const Variant& p_data);
|
_FORCE_INLINE_ void project_range_cast(const Vector2& p_cast, const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
|
||||||
virtual Variant get_data() const;
|
//real large
|
||||||
|
r_min=-1e10;
|
||||||
_FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
|
r_max=1e10;
|
||||||
//real large
|
}
|
||||||
r_max = p_normal.dot(p_transform.xform(a));
|
|
||||||
r_min = p_normal.dot(p_transform.xform(b));
|
|
||||||
if (r_max<r_min) {
|
|
||||||
|
};
|
||||||
SWAP(r_max,r_min);
|
|
||||||
}
|
|
||||||
}
|
class RayShape2DSW : public Shape2DSW {
|
||||||
|
|
||||||
_FORCE_INLINE_ SegmentShape2DSW() {}
|
|
||||||
_FORCE_INLINE_ SegmentShape2DSW(const Vector2& p_a,const Vector2& p_b,const Vector2& p_n) { a=p_a; b=p_b; n=p_n; }
|
real_t length;
|
||||||
};
|
|
||||||
|
public:
|
||||||
|
|
||||||
class CircleShape2DSW : public Shape2DSW {
|
|
||||||
|
_FORCE_INLINE_ real_t get_length() const { return length; }
|
||||||
|
|
||||||
real_t radius;
|
virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_RAY; }
|
||||||
|
|
||||||
public:
|
virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
|
||||||
|
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
|
||||||
_FORCE_INLINE_ const real_t& get_radius() const { return radius; }
|
|
||||||
|
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
|
||||||
virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_CIRCLE; }
|
virtual real_t get_moment_of_inertia(float p_mass) const;
|
||||||
|
|
||||||
virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
|
virtual void set_data(const Variant& p_data);
|
||||||
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
|
virtual Variant get_data() const;
|
||||||
|
|
||||||
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
|
_FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
|
||||||
virtual real_t get_moment_of_inertia(float p_mass) const;
|
//real large
|
||||||
|
r_max = p_normal.dot(p_transform.get_origin());
|
||||||
virtual void set_data(const Variant& p_data);
|
r_min = p_normal.dot(p_transform.xform(Vector2(0,length)));
|
||||||
virtual Variant get_data() const;
|
if (r_max<r_min) {
|
||||||
|
|
||||||
_FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
|
SWAP(r_max,r_min);
|
||||||
//real large
|
}
|
||||||
real_t d = p_normal.dot( p_transform.get_origin() );
|
}
|
||||||
|
|
||||||
// figure out scale at point
|
DEFAULT_PROJECT_RANGE_CAST
|
||||||
Vector2 local_normal = p_transform.basis_xform_inv(p_normal);
|
|
||||||
real_t scale = local_normal.length();
|
|
||||||
|
_FORCE_INLINE_ RayShape2DSW() {}
|
||||||
r_min = d - (radius) * scale;
|
_FORCE_INLINE_ RayShape2DSW(real_t p_length) { length=p_length; }
|
||||||
r_max = d + (radius) * scale;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
};
|
class SegmentShape2DSW : public Shape2DSW {
|
||||||
|
|
||||||
|
|
||||||
|
Vector2 a;
|
||||||
class RectangleShape2DSW : public Shape2DSW {
|
Vector2 b;
|
||||||
|
Vector2 n;
|
||||||
|
|
||||||
Vector2 half_extents;
|
public:
|
||||||
|
|
||||||
public:
|
|
||||||
|
_FORCE_INLINE_ const Vector2& get_a() const { return a; }
|
||||||
_FORCE_INLINE_ const Vector2& get_half_extents() const { return half_extents; }
|
_FORCE_INLINE_ const Vector2& get_b() const { return b; }
|
||||||
|
_FORCE_INLINE_ const Vector2& get_normal() const { return n; }
|
||||||
virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_RECTANGLE; }
|
|
||||||
|
virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_SEGMENT; }
|
||||||
virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
|
|
||||||
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
|
_FORCE_INLINE_ Vector2 get_xformed_normal(const Matrix32& p_xform) const {
|
||||||
|
|
||||||
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
|
return (p_xform.xform(b) - p_xform.xform(a)).normalized().tangent();
|
||||||
virtual real_t get_moment_of_inertia(float p_mass) const;
|
}
|
||||||
|
virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
|
||||||
virtual void set_data(const Variant& p_data);
|
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
|
||||||
virtual Variant get_data() const;
|
|
||||||
|
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
|
||||||
_FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
|
virtual real_t get_moment_of_inertia(float p_mass) const;
|
||||||
// no matter the angle, the box is mirrored anyway
|
|
||||||
Vector2 local_normal=p_transform.basis_xform_inv(p_normal);
|
virtual void set_data(const Variant& p_data);
|
||||||
|
virtual Variant get_data() const;
|
||||||
float length = local_normal.abs().dot(half_extents);
|
|
||||||
float distance = p_normal.dot( p_transform.get_origin() );
|
_FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
|
||||||
|
//real large
|
||||||
r_min = distance - length;
|
r_max = p_normal.dot(p_transform.xform(a));
|
||||||
r_max = distance + length;
|
r_min = p_normal.dot(p_transform.xform(b));
|
||||||
}
|
if (r_max<r_min) {
|
||||||
|
|
||||||
};
|
SWAP(r_max,r_min);
|
||||||
|
}
|
||||||
class CapsuleShape2DSW : public Shape2DSW {
|
}
|
||||||
|
|
||||||
|
DEFAULT_PROJECT_RANGE_CAST
|
||||||
real_t radius;
|
|
||||||
real_t height;
|
_FORCE_INLINE_ SegmentShape2DSW() {}
|
||||||
|
_FORCE_INLINE_ SegmentShape2DSW(const Vector2& p_a,const Vector2& p_b,const Vector2& p_n) { a=p_a; b=p_b; n=p_n; }
|
||||||
public:
|
};
|
||||||
|
|
||||||
_FORCE_INLINE_ const real_t& get_radius() const { return radius; }
|
|
||||||
_FORCE_INLINE_ const real_t& get_height() const { return height; }
|
class CircleShape2DSW : public Shape2DSW {
|
||||||
|
|
||||||
virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_CAPSULE; }
|
|
||||||
|
real_t radius;
|
||||||
virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
|
|
||||||
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
|
public:
|
||||||
|
|
||||||
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
|
_FORCE_INLINE_ const real_t& get_radius() const { return radius; }
|
||||||
virtual real_t get_moment_of_inertia(float p_mass) const;
|
|
||||||
|
virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_CIRCLE; }
|
||||||
virtual void set_data(const Variant& p_data);
|
|
||||||
virtual Variant get_data() const;
|
virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
|
||||||
|
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
|
||||||
_FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
|
|
||||||
// no matter the angle, the box is mirrored anyway
|
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
|
||||||
Vector2 n=p_transform.basis_xform_inv(p_normal).normalized();
|
virtual real_t get_moment_of_inertia(float p_mass) const;
|
||||||
float h = (n.y > 0) ? height : -height;
|
|
||||||
|
virtual void set_data(const Variant& p_data);
|
||||||
n *= radius;
|
virtual Variant get_data() const;
|
||||||
n.y += h * 0.5;
|
|
||||||
|
_FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
|
||||||
r_max = p_normal.dot(p_transform.xform(n));
|
//real large
|
||||||
r_min = p_normal.dot(p_transform.xform(-n));
|
real_t d = p_normal.dot( p_transform.get_origin() );
|
||||||
|
|
||||||
if (r_max<r_min) {
|
// figure out scale at point
|
||||||
|
Vector2 local_normal = p_transform.basis_xform_inv(p_normal);
|
||||||
SWAP(r_max,r_min);
|
real_t scale = local_normal.length();
|
||||||
}
|
|
||||||
|
r_min = d - (radius) * scale;
|
||||||
//ERR_FAIL_COND( r_max < r_min );
|
r_max = d + (radius) * scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
|
||||||
|
DEFAULT_PROJECT_RANGE_CAST
|
||||||
|
|
||||||
class ConvexPolygonShape2DSW : public Shape2DSW {
|
};
|
||||||
|
|
||||||
|
|
||||||
struct Point {
|
|
||||||
|
class RectangleShape2DSW : public Shape2DSW {
|
||||||
Vector2 pos;
|
|
||||||
Vector2 normal; //normal to next segment
|
|
||||||
};
|
Vector2 half_extents;
|
||||||
|
|
||||||
Point *points;
|
public:
|
||||||
int point_count;
|
|
||||||
|
_FORCE_INLINE_ const Vector2& get_half_extents() const { return half_extents; }
|
||||||
public:
|
|
||||||
|
virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_RECTANGLE; }
|
||||||
_FORCE_INLINE_ int get_point_count() const { return point_count; }
|
|
||||||
_FORCE_INLINE_ const Vector2& get_point(int p_idx) const { return points[p_idx].pos; }
|
virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
|
||||||
_FORCE_INLINE_ const Vector2& get_segment_normal(int p_idx) const { return points[p_idx].normal; }
|
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
|
||||||
|
|
||||||
virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_CONVEX_POLYGON; }
|
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
|
||||||
|
virtual real_t get_moment_of_inertia(float p_mass) const;
|
||||||
virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
|
|
||||||
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
|
virtual void set_data(const Variant& p_data);
|
||||||
|
virtual Variant get_data() const;
|
||||||
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
|
|
||||||
virtual real_t get_moment_of_inertia(float p_mass) const;
|
_FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
|
||||||
|
// no matter the angle, the box is mirrored anyway
|
||||||
virtual void set_data(const Variant& p_data);
|
Vector2 local_normal=p_transform.basis_xform_inv(p_normal);
|
||||||
virtual Variant get_data() const;
|
|
||||||
|
float length = local_normal.abs().dot(half_extents);
|
||||||
_FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
|
float distance = p_normal.dot( p_transform.get_origin() );
|
||||||
// no matter the angle, the box is mirrored anyway
|
|
||||||
|
r_min = distance - length;
|
||||||
r_min = r_max = p_normal.dot(p_transform.xform(points[0].pos));
|
r_max = distance + length;
|
||||||
for(int i=1;i<point_count;i++) {
|
}
|
||||||
|
|
||||||
float d = p_normal.dot(p_transform.xform(points[i].pos));
|
DEFAULT_PROJECT_RANGE_CAST
|
||||||
if (d>r_max)
|
|
||||||
r_max=d;
|
};
|
||||||
if (d<r_min)
|
|
||||||
r_min=d;
|
class CapsuleShape2DSW : public Shape2DSW {
|
||||||
|
|
||||||
}
|
|
||||||
|
real_t radius;
|
||||||
}
|
real_t height;
|
||||||
|
|
||||||
|
public:
|
||||||
ConvexPolygonShape2DSW();
|
|
||||||
~ConvexPolygonShape2DSW();
|
_FORCE_INLINE_ const real_t& get_radius() const { return radius; }
|
||||||
};
|
_FORCE_INLINE_ const real_t& get_height() const { return height; }
|
||||||
|
|
||||||
|
virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_CAPSULE; }
|
||||||
class ConcaveShape2DSW : public Shape2DSW {
|
|
||||||
|
virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
|
||||||
public:
|
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
|
||||||
|
|
||||||
virtual bool is_concave() const { return true; }
|
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
|
||||||
typedef void (*Callback)(void* p_userdata,Shape2DSW *p_convex);
|
virtual real_t get_moment_of_inertia(float p_mass) const;
|
||||||
|
|
||||||
virtual void cull(const Rect2& p_local_aabb,Callback p_callback,void* p_userdata) const=0;
|
virtual void set_data(const Variant& p_data);
|
||||||
|
virtual Variant get_data() const;
|
||||||
};
|
|
||||||
|
_FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
|
||||||
class ConcavePolygonShape2DSW : public ConcaveShape2DSW {
|
// no matter the angle, the box is mirrored anyway
|
||||||
|
Vector2 n=p_transform.basis_xform_inv(p_normal).normalized();
|
||||||
struct Segment {
|
float h = (n.y > 0) ? height : -height;
|
||||||
|
|
||||||
int points[2];
|
n *= radius;
|
||||||
};
|
n.y += h * 0.5;
|
||||||
|
|
||||||
Vector<Segment> segments;
|
r_max = p_normal.dot(p_transform.xform(n));
|
||||||
Vector<Point2> points;
|
r_min = p_normal.dot(p_transform.xform(-n));
|
||||||
|
|
||||||
struct BVH {
|
if (r_max<r_min) {
|
||||||
|
|
||||||
Rect2 aabb;
|
SWAP(r_max,r_min);
|
||||||
int left,right;
|
}
|
||||||
};
|
|
||||||
|
//ERR_FAIL_COND( r_max < r_min );
|
||||||
|
}
|
||||||
Vector<BVH> bvh;
|
|
||||||
int bvh_depth;
|
DEFAULT_PROJECT_RANGE_CAST
|
||||||
|
|
||||||
|
};
|
||||||
struct BVH_CompareX {
|
|
||||||
|
|
||||||
_FORCE_INLINE_ bool operator ()(const BVH& a, const BVH& b) const {
|
|
||||||
|
|
||||||
return (a.aabb.pos.x+a.aabb.size.x*0.5) < (b.aabb.pos.x+b.aabb.size.x*0.5);
|
class ConvexPolygonShape2DSW : public Shape2DSW {
|
||||||
}
|
|
||||||
};
|
|
||||||
|
struct Point {
|
||||||
struct BVH_CompareY {
|
|
||||||
|
Vector2 pos;
|
||||||
_FORCE_INLINE_ bool operator ()(const BVH& a, const BVH& b) const {
|
Vector2 normal; //normal to next segment
|
||||||
|
};
|
||||||
return (a.aabb.pos.y+a.aabb.size.y*0.5) < (b.aabb.pos.y+b.aabb.size.y*0.5);
|
|
||||||
}
|
Point *points;
|
||||||
};
|
int point_count;
|
||||||
|
|
||||||
int _generate_bvh(BVH *p_bvh,int p_len,int p_depth);
|
public:
|
||||||
|
|
||||||
public:
|
_FORCE_INLINE_ int get_point_count() const { return point_count; }
|
||||||
|
_FORCE_INLINE_ const Vector2& get_point(int p_idx) const { return points[p_idx].pos; }
|
||||||
virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_CONCAVE_POLYGON; }
|
_FORCE_INLINE_ const Vector2& get_segment_normal(int p_idx) const { return points[p_idx].normal; }
|
||||||
|
_FORCE_INLINE_ Vector2 get_xformed_segment_normal(const Matrix32& p_xform, int p_idx) const {
|
||||||
virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { /*project_range(p_normal,p_transform,r_min,r_max);*/ }
|
|
||||||
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
|
Vector2 a = points[p_idx].pos;
|
||||||
|
p_idx++;
|
||||||
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
|
Vector2 b = points[p_idx==point_count?0:p_idx].pos;
|
||||||
|
return (p_xform.xform(b)-p_xform.xform(a)).normalized().tangent();
|
||||||
virtual real_t get_moment_of_inertia(float p_mass) const { return 0; }
|
}
|
||||||
|
|
||||||
virtual void set_data(const Variant& p_data);
|
virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_CONVEX_POLYGON; }
|
||||||
virtual Variant get_data() const;
|
|
||||||
|
virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
|
||||||
virtual void cull(const Rect2& p_local_aabb,Callback p_callback,void* p_userdata) const;
|
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
|
||||||
|
|
||||||
};
|
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
|
||||||
|
virtual real_t get_moment_of_inertia(float p_mass) const;
|
||||||
|
|
||||||
#endif // SHAPE_2D_2DSW_H
|
virtual void set_data(const Variant& p_data);
|
||||||
|
virtual Variant get_data() const;
|
||||||
|
|
||||||
|
_FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
|
||||||
|
// no matter the angle, the box is mirrored anyway
|
||||||
|
|
||||||
|
r_min = r_max = p_normal.dot(p_transform.xform(points[0].pos));
|
||||||
|
for(int i=1;i<point_count;i++) {
|
||||||
|
|
||||||
|
float d = p_normal.dot(p_transform.xform(points[i].pos));
|
||||||
|
if (d>r_max)
|
||||||
|
r_max=d;
|
||||||
|
if (d<r_min)
|
||||||
|
r_min=d;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFAULT_PROJECT_RANGE_CAST
|
||||||
|
|
||||||
|
ConvexPolygonShape2DSW();
|
||||||
|
~ConvexPolygonShape2DSW();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ConcaveShape2DSW : public Shape2DSW {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual bool is_concave() const { return true; }
|
||||||
|
typedef void (*Callback)(void* p_userdata,Shape2DSW *p_convex);
|
||||||
|
|
||||||
|
virtual void cull(const Rect2& p_local_aabb,Callback p_callback,void* p_userdata) const=0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class ConcavePolygonShape2DSW : public ConcaveShape2DSW {
|
||||||
|
|
||||||
|
struct Segment {
|
||||||
|
|
||||||
|
int points[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
Vector<Segment> segments;
|
||||||
|
Vector<Point2> points;
|
||||||
|
|
||||||
|
struct BVH {
|
||||||
|
|
||||||
|
Rect2 aabb;
|
||||||
|
int left,right;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Vector<BVH> bvh;
|
||||||
|
int bvh_depth;
|
||||||
|
|
||||||
|
|
||||||
|
struct BVH_CompareX {
|
||||||
|
|
||||||
|
_FORCE_INLINE_ bool operator ()(const BVH& a, const BVH& b) const {
|
||||||
|
|
||||||
|
return (a.aabb.pos.x+a.aabb.size.x*0.5) < (b.aabb.pos.x+b.aabb.size.x*0.5);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BVH_CompareY {
|
||||||
|
|
||||||
|
_FORCE_INLINE_ bool operator ()(const BVH& a, const BVH& b) const {
|
||||||
|
|
||||||
|
return (a.aabb.pos.y+a.aabb.size.y*0.5) < (b.aabb.pos.y+b.aabb.size.y*0.5);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int _generate_bvh(BVH *p_bvh,int p_len,int p_depth);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_CONCAVE_POLYGON; }
|
||||||
|
|
||||||
|
virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { /*project_range(p_normal,p_transform,r_min,r_max);*/ }
|
||||||
|
virtual void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { /*project_range(p_normal,p_transform,r_min,r_max);*/ }
|
||||||
|
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
|
||||||
|
|
||||||
|
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
|
||||||
|
|
||||||
|
virtual real_t get_moment_of_inertia(float p_mass) const { return 0; }
|
||||||
|
|
||||||
|
virtual void set_data(const Variant& p_data);
|
||||||
|
virtual Variant get_data() const;
|
||||||
|
|
||||||
|
virtual void cull(const Rect2& p_local_aabb,Callback p_callback,void* p_userdata) const;
|
||||||
|
|
||||||
|
|
||||||
|
DEFAULT_PROJECT_RANGE_CAST
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SHAPE_2D_2DSW_H
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -26,135 +26,136 @@
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
#ifndef SPACE_2D_SW_H
|
#ifndef SPACE_2D_SW_H
|
||||||
#define SPACE_2D_SW_H
|
#define SPACE_2D_SW_H
|
||||||
|
|
||||||
#include "typedefs.h"
|
#include "typedefs.h"
|
||||||
#include "hash_map.h"
|
#include "hash_map.h"
|
||||||
#include "body_2d_sw.h"
|
#include "body_2d_sw.h"
|
||||||
#include "area_2d_sw.h"
|
#include "area_2d_sw.h"
|
||||||
#include "body_pair_2d_sw.h"
|
#include "body_pair_2d_sw.h"
|
||||||
#include "area_pair_2d_sw.h"
|
#include "area_pair_2d_sw.h"
|
||||||
#include "broad_phase_2d_sw.h"
|
#include "broad_phase_2d_sw.h"
|
||||||
#include "collision_object_2d_sw.h"
|
#include "collision_object_2d_sw.h"
|
||||||
|
|
||||||
|
|
||||||
class Physics2DDirectSpaceStateSW : public Physics2DDirectSpaceState {
|
class Physics2DDirectSpaceStateSW : public Physics2DDirectSpaceState {
|
||||||
|
|
||||||
OBJ_TYPE( Physics2DDirectSpaceStateSW, Physics2DDirectSpaceState );
|
OBJ_TYPE( Physics2DDirectSpaceStateSW, Physics2DDirectSpaceState );
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Space2DSW *space;
|
Space2DSW *space;
|
||||||
|
|
||||||
bool intersect_ray(const Vector2& p_from, const Vector2& p_to,RayResult &r_result,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_user_mask=0);
|
bool intersect_ray(const Vector2& p_from, const Vector2& p_to,RayResult &r_result,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_user_mask=0);
|
||||||
int intersect_shape(const RID& p_shape, const Matrix32& p_xform,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_user_mask=0);
|
int intersect_shape(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_user_mask=0);
|
||||||
|
bool cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion, MotionCastCollision &r_result, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_user_mask=0);
|
||||||
Physics2DDirectSpaceStateSW();
|
|
||||||
};
|
Physics2DDirectSpaceStateSW();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class Space2DSW {
|
|
||||||
|
class Space2DSW {
|
||||||
|
|
||||||
Physics2DDirectSpaceStateSW *direct_access;
|
|
||||||
RID self;
|
Physics2DDirectSpaceStateSW *direct_access;
|
||||||
|
RID self;
|
||||||
BroadPhase2DSW *broadphase;
|
|
||||||
SelfList<Body2DSW>::List active_list;
|
BroadPhase2DSW *broadphase;
|
||||||
SelfList<Body2DSW>::List inertia_update_list;
|
SelfList<Body2DSW>::List active_list;
|
||||||
SelfList<Body2DSW>::List state_query_list;
|
SelfList<Body2DSW>::List inertia_update_list;
|
||||||
SelfList<Area2DSW>::List monitor_query_list;
|
SelfList<Body2DSW>::List state_query_list;
|
||||||
SelfList<Area2DSW>::List area_moved_list;
|
SelfList<Area2DSW>::List monitor_query_list;
|
||||||
|
SelfList<Area2DSW>::List area_moved_list;
|
||||||
static void* _broadphase_pair(CollisionObject2DSW *A,int p_subindex_A,CollisionObject2DSW *B,int p_subindex_B,void *p_self);
|
|
||||||
static void _broadphase_unpair(CollisionObject2DSW *A,int p_subindex_A,CollisionObject2DSW *B,int p_subindex_B,void *p_data,void *p_self);
|
static void* _broadphase_pair(CollisionObject2DSW *A,int p_subindex_A,CollisionObject2DSW *B,int p_subindex_B,void *p_self);
|
||||||
|
static void _broadphase_unpair(CollisionObject2DSW *A,int p_subindex_A,CollisionObject2DSW *B,int p_subindex_B,void *p_data,void *p_self);
|
||||||
Set<CollisionObject2DSW*> objects;
|
|
||||||
|
Set<CollisionObject2DSW*> objects;
|
||||||
Area2DSW *area;
|
|
||||||
|
Area2DSW *area;
|
||||||
real_t contact_recycle_radius;
|
|
||||||
real_t contact_max_separation;
|
real_t contact_recycle_radius;
|
||||||
real_t contact_max_allowed_penetration;
|
real_t contact_max_separation;
|
||||||
real_t constraint_bias;
|
real_t contact_max_allowed_penetration;
|
||||||
|
real_t constraint_bias;
|
||||||
enum {
|
|
||||||
|
enum {
|
||||||
INTERSECTION_QUERY_MAX=2048
|
|
||||||
};
|
INTERSECTION_QUERY_MAX=2048
|
||||||
|
};
|
||||||
CollisionObject2DSW *intersection_query_results[INTERSECTION_QUERY_MAX];
|
|
||||||
int intersection_query_subindex_results[INTERSECTION_QUERY_MAX];
|
CollisionObject2DSW *intersection_query_results[INTERSECTION_QUERY_MAX];
|
||||||
|
int intersection_query_subindex_results[INTERSECTION_QUERY_MAX];
|
||||||
float body_linear_velocity_sleep_treshold;
|
|
||||||
float body_angular_velocity_sleep_treshold;
|
float body_linear_velocity_sleep_treshold;
|
||||||
float body_time_to_sleep;
|
float body_angular_velocity_sleep_treshold;
|
||||||
float body_angular_velocity_damp_ratio;
|
float body_time_to_sleep;
|
||||||
|
float body_angular_velocity_damp_ratio;
|
||||||
bool locked;
|
|
||||||
|
bool locked;
|
||||||
friend class Physics2DDirectSpaceStateSW;
|
|
||||||
|
friend class Physics2DDirectSpaceStateSW;
|
||||||
public:
|
|
||||||
|
public:
|
||||||
_FORCE_INLINE_ void set_self(const RID& p_self) { self=p_self; }
|
|
||||||
_FORCE_INLINE_ RID get_self() const { return self; }
|
_FORCE_INLINE_ void set_self(const RID& p_self) { self=p_self; }
|
||||||
|
_FORCE_INLINE_ RID get_self() const { return self; }
|
||||||
void set_default_area(Area2DSW *p_area) { area=p_area; }
|
|
||||||
Area2DSW *get_default_area() const { return area; }
|
void set_default_area(Area2DSW *p_area) { area=p_area; }
|
||||||
|
Area2DSW *get_default_area() const { return area; }
|
||||||
const SelfList<Body2DSW>::List& get_active_body_list() const;
|
|
||||||
void body_add_to_active_list(SelfList<Body2DSW>* p_body);
|
const SelfList<Body2DSW>::List& get_active_body_list() const;
|
||||||
void body_remove_from_active_list(SelfList<Body2DSW>* p_body);
|
void body_add_to_active_list(SelfList<Body2DSW>* p_body);
|
||||||
void body_add_to_inertia_update_list(SelfList<Body2DSW>* p_body);
|
void body_remove_from_active_list(SelfList<Body2DSW>* p_body);
|
||||||
void body_remove_from_inertia_update_list(SelfList<Body2DSW>* p_body);
|
void body_add_to_inertia_update_list(SelfList<Body2DSW>* p_body);
|
||||||
void area_add_to_moved_list(SelfList<Area2DSW>* p_area);
|
void body_remove_from_inertia_update_list(SelfList<Body2DSW>* p_body);
|
||||||
void area_remove_from_moved_list(SelfList<Area2DSW>* p_area);
|
void area_add_to_moved_list(SelfList<Area2DSW>* p_area);
|
||||||
const SelfList<Area2DSW>::List& get_moved_area_list() const;
|
void area_remove_from_moved_list(SelfList<Area2DSW>* p_area);
|
||||||
|
const SelfList<Area2DSW>::List& get_moved_area_list() const;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void body_add_to_state_query_list(SelfList<Body2DSW>* p_body);
|
|
||||||
void body_remove_from_state_query_list(SelfList<Body2DSW>* p_body);
|
void body_add_to_state_query_list(SelfList<Body2DSW>* p_body);
|
||||||
|
void body_remove_from_state_query_list(SelfList<Body2DSW>* p_body);
|
||||||
void area_add_to_monitor_query_list(SelfList<Area2DSW>* p_area);
|
|
||||||
void area_remove_from_monitor_query_list(SelfList<Area2DSW>* p_area);
|
void area_add_to_monitor_query_list(SelfList<Area2DSW>* p_area);
|
||||||
|
void area_remove_from_monitor_query_list(SelfList<Area2DSW>* p_area);
|
||||||
BroadPhase2DSW *get_broadphase();
|
|
||||||
|
BroadPhase2DSW *get_broadphase();
|
||||||
void add_object(CollisionObject2DSW *p_object);
|
|
||||||
void remove_object(CollisionObject2DSW *p_object);
|
void add_object(CollisionObject2DSW *p_object);
|
||||||
const Set<CollisionObject2DSW*> &get_objects() const;
|
void remove_object(CollisionObject2DSW *p_object);
|
||||||
|
const Set<CollisionObject2DSW*> &get_objects() const;
|
||||||
_FORCE_INLINE_ real_t get_contact_recycle_radius() const { return contact_recycle_radius; }
|
|
||||||
_FORCE_INLINE_ real_t get_contact_max_separation() const { return contact_max_separation; }
|
_FORCE_INLINE_ real_t get_contact_recycle_radius() const { return contact_recycle_radius; }
|
||||||
_FORCE_INLINE_ real_t get_contact_max_allowed_penetration() const { return contact_max_allowed_penetration; }
|
_FORCE_INLINE_ real_t get_contact_max_separation() const { return contact_max_separation; }
|
||||||
_FORCE_INLINE_ real_t get_constraint_bias() const { return constraint_bias; }
|
_FORCE_INLINE_ real_t get_contact_max_allowed_penetration() const { return contact_max_allowed_penetration; }
|
||||||
_FORCE_INLINE_ real_t get_body_linear_velocity_sleep_treshold() const { return body_linear_velocity_sleep_treshold; }
|
_FORCE_INLINE_ real_t get_constraint_bias() const { return constraint_bias; }
|
||||||
_FORCE_INLINE_ real_t get_body_angular_velocity_sleep_treshold() const { return body_angular_velocity_sleep_treshold; }
|
_FORCE_INLINE_ real_t get_body_linear_velocity_sleep_treshold() const { return body_linear_velocity_sleep_treshold; }
|
||||||
_FORCE_INLINE_ real_t get_body_time_to_sleep() const { return body_time_to_sleep; }
|
_FORCE_INLINE_ real_t get_body_angular_velocity_sleep_treshold() const { return body_angular_velocity_sleep_treshold; }
|
||||||
_FORCE_INLINE_ real_t get_body_angular_velocity_damp_ratio() const { return body_angular_velocity_damp_ratio; }
|
_FORCE_INLINE_ real_t get_body_time_to_sleep() const { return body_time_to_sleep; }
|
||||||
|
_FORCE_INLINE_ real_t get_body_angular_velocity_damp_ratio() const { return body_angular_velocity_damp_ratio; }
|
||||||
|
|
||||||
void update();
|
|
||||||
void setup();
|
void update();
|
||||||
void call_queries();
|
void setup();
|
||||||
|
void call_queries();
|
||||||
|
|
||||||
bool is_locked() const;
|
|
||||||
void lock();
|
bool is_locked() const;
|
||||||
void unlock();
|
void lock();
|
||||||
|
void unlock();
|
||||||
void set_param(Physics2DServer::SpaceParameter p_param, real_t p_value);
|
|
||||||
real_t get_param(Physics2DServer::SpaceParameter p_param) const;
|
void set_param(Physics2DServer::SpaceParameter p_param, real_t p_value);
|
||||||
|
real_t get_param(Physics2DServer::SpaceParameter p_param) const;
|
||||||
Physics2DDirectSpaceStateSW *get_direct_state();
|
|
||||||
|
Physics2DDirectSpaceStateSW *get_direct_state();
|
||||||
Space2DSW();
|
|
||||||
~Space2DSW();
|
Space2DSW();
|
||||||
};
|
~Space2DSW();
|
||||||
|
};
|
||||||
|
|
||||||
#endif // SPACE_2D_SW_H
|
|
||||||
|
#endif // SPACE_2D_SW_H
|
||||||
|
|
|
@ -49,7 +49,7 @@ void Step2DSW::_populate_island(Body2DSW* p_body,Body2DSW** p_island,Constraint2
|
||||||
if (i==E->get())
|
if (i==E->get())
|
||||||
continue;
|
continue;
|
||||||
Body2DSW *b = c->get_body_ptr()[i];
|
Body2DSW *b = c->get_body_ptr()[i];
|
||||||
if (b->get_island_step()==_step || b->get_mode()==Physics2DServer::BODY_MODE_STATIC)
|
if (b->get_island_step()==_step || b->get_mode()==Physics2DServer::BODY_MODE_STATIC || b->get_mode()==Physics2DServer::BODY_MODE_KINEMATIC)
|
||||||
continue; //no go
|
continue; //no go
|
||||||
_populate_island(c->get_body_ptr()[i],p_island,p_constraint_island);
|
_populate_island(c->get_body_ptr()[i],p_island,p_constraint_island);
|
||||||
}
|
}
|
||||||
|
@ -87,8 +87,10 @@ void Step2DSW::_check_suspend(Body2DSW *p_island,float p_delta) {
|
||||||
Body2DSW *b = p_island;
|
Body2DSW *b = p_island;
|
||||||
while(b) {
|
while(b) {
|
||||||
|
|
||||||
if (b->get_mode()==Physics2DServer::BODY_MODE_STATIC)
|
if (b->get_mode()==Physics2DServer::BODY_MODE_STATIC || b->get_mode()==Physics2DServer::BODY_MODE_KINEMATIC) {
|
||||||
|
b=b->get_island_next();
|
||||||
continue; //ignore for static
|
continue; //ignore for static
|
||||||
|
}
|
||||||
|
|
||||||
if (!b->sleep_test(p_delta))
|
if (!b->sleep_test(p_delta))
|
||||||
can_sleep=false;
|
can_sleep=false;
|
||||||
|
@ -101,8 +103,10 @@ void Step2DSW::_check_suspend(Body2DSW *p_island,float p_delta) {
|
||||||
b = p_island;
|
b = p_island;
|
||||||
while(b) {
|
while(b) {
|
||||||
|
|
||||||
if (b->get_mode()==Physics2DServer::BODY_MODE_STATIC)
|
if (b->get_mode()==Physics2DServer::BODY_MODE_STATIC || b->get_mode()==Physics2DServer::BODY_MODE_KINEMATIC) {
|
||||||
|
b=b->get_island_next();
|
||||||
continue; //ignore for static
|
continue; //ignore for static
|
||||||
|
}
|
||||||
|
|
||||||
bool active = b->is_active();
|
bool active = b->is_active();
|
||||||
|
|
||||||
|
@ -210,8 +214,9 @@ void Step2DSW::step(Space2DSW* p_space,float p_delta,int p_iterations) {
|
||||||
b = body_list->first();
|
b = body_list->first();
|
||||||
while(b) {
|
while(b) {
|
||||||
|
|
||||||
|
const SelfList<Body2DSW>*n=b->next();
|
||||||
b->self()->integrate_velocities(p_delta);
|
b->self()->integrate_velocities(p_delta);
|
||||||
b=b->next();
|
b=n; // in case it shuts itself down
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SLEEP / WAKE UP ISLANDS */
|
/* SLEEP / WAKE UP ISLANDS */
|
||||||
|
|
|
@ -122,7 +122,7 @@ Variant Physics2DDirectSpaceState::_intersect_ray(const Vector2& p_from, const V
|
||||||
if (!res)
|
if (!res)
|
||||||
return Variant();
|
return Variant();
|
||||||
|
|
||||||
Dictionary d;
|
Dictionary d(true);
|
||||||
d["position"]=inters.position;
|
d["position"]=inters.position;
|
||||||
d["normal"]=inters.normal;
|
d["normal"]=inters.normal;
|
||||||
d["collider_id"]=inters.collider_id;
|
d["collider_id"]=inters.collider_id;
|
||||||
|
@ -145,7 +145,7 @@ Variant Physics2DDirectSpaceState::_intersect_shape(const RID& p_shape, const Ma
|
||||||
|
|
||||||
ShapeResult *res=(ShapeResult*)alloca(p_result_max*sizeof(ShapeResult));
|
ShapeResult *res=(ShapeResult*)alloca(p_result_max*sizeof(ShapeResult));
|
||||||
|
|
||||||
int rc = intersect_shape(p_shape,p_xform,res,p_result_max,exclude,p_user_mask);
|
int rc = intersect_shape(p_shape,p_xform,Vector2(),res,p_result_max,exclude,p_user_mask);
|
||||||
|
|
||||||
if (rc==0)
|
if (rc==0)
|
||||||
return Variant();
|
return Variant();
|
||||||
|
@ -160,6 +160,34 @@ Variant Physics2DDirectSpaceState::_intersect_shape(const RID& p_shape, const Ma
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Variant Physics2DDirectSpaceState::_cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,const Vector<RID>& p_exclude,uint32_t p_user_mask) {
|
||||||
|
|
||||||
|
|
||||||
|
Set<RID> exclude;
|
||||||
|
for(int i=0;i<p_exclude.size();i++)
|
||||||
|
exclude.insert(p_exclude[i]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
MotionCastCollision mcc;
|
||||||
|
|
||||||
|
bool result = cast_motion(p_shape,p_xform,p_motion,mcc,exclude,p_user_mask);
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
return Variant();
|
||||||
|
|
||||||
|
Dictionary d(true);
|
||||||
|
d["point"]=mcc.point;
|
||||||
|
d["normal"]=mcc.normal;
|
||||||
|
d["rid"]=mcc.rid;
|
||||||
|
d["collider_id"]=mcc.collider_id;
|
||||||
|
d["collider"]=mcc.collider;
|
||||||
|
d["shape"]=mcc.shape;
|
||||||
|
|
||||||
|
return d;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -175,6 +203,7 @@ void Physics2DDirectSpaceState::_bind_methods() {
|
||||||
|
|
||||||
ObjectTypeDB::bind_method(_MD("intersect_ray:Dictionary","from","to","exclude","umask"),&Physics2DDirectSpaceState::_intersect_ray,DEFVAL(Array()),DEFVAL(0));
|
ObjectTypeDB::bind_method(_MD("intersect_ray:Dictionary","from","to","exclude","umask"),&Physics2DDirectSpaceState::_intersect_ray,DEFVAL(Array()),DEFVAL(0));
|
||||||
ObjectTypeDB::bind_method(_MD("intersect_shape:Physics2DShapeQueryResult","shape","xform","result_max","exclude","umask"),&Physics2DDirectSpaceState::_intersect_shape,DEFVAL(Array()),DEFVAL(0));
|
ObjectTypeDB::bind_method(_MD("intersect_shape:Physics2DShapeQueryResult","shape","xform","result_max","exclude","umask"),&Physics2DDirectSpaceState::_intersect_shape,DEFVAL(Array()),DEFVAL(0));
|
||||||
|
ObjectTypeDB::bind_method(_MD("cast_motion","shape","xform","motion","exclude","umask"),&Physics2DDirectSpaceState::_intersect_shape,DEFVAL(Array()),DEFVAL(0));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,8 +326,8 @@ void Physics2DServer::_bind_methods() {
|
||||||
ObjectTypeDB::bind_method(_MD("body_get_object_instance_ID","body"),&Physics2DServer::body_get_object_instance_ID);
|
ObjectTypeDB::bind_method(_MD("body_get_object_instance_ID","body"),&Physics2DServer::body_get_object_instance_ID);
|
||||||
|
|
||||||
|
|
||||||
ObjectTypeDB::bind_method(_MD("body_set_enable_continuous_collision_detection","body","enable"),&Physics2DServer::body_set_enable_continuous_collision_detection);
|
ObjectTypeDB::bind_method(_MD("body_set_continuous_collision_detection_mode","body","mode"),&Physics2DServer::body_set_continuous_collision_detection_mode);
|
||||||
ObjectTypeDB::bind_method(_MD("body_is_continuous_collision_detection_enabled","body"),&Physics2DServer::body_is_continuous_collision_detection_enabled);
|
ObjectTypeDB::bind_method(_MD("body_get_continuous_collision_detection_mode","body"),&Physics2DServer::body_get_continuous_collision_detection_mode);
|
||||||
|
|
||||||
|
|
||||||
//ObjectTypeDB::bind_method(_MD("body_set_user_flags","flags""),&Physics2DServer::body_set_shape,DEFVAL(Matrix32));
|
//ObjectTypeDB::bind_method(_MD("body_set_user_flags","flags""),&Physics2DServer::body_set_shape,DEFVAL(Matrix32));
|
||||||
|
@ -307,8 +336,6 @@ void Physics2DServer::_bind_methods() {
|
||||||
ObjectTypeDB::bind_method(_MD("body_set_param","body","param","value"),&Physics2DServer::body_set_param);
|
ObjectTypeDB::bind_method(_MD("body_set_param","body","param","value"),&Physics2DServer::body_set_param);
|
||||||
ObjectTypeDB::bind_method(_MD("body_get_param","body","param"),&Physics2DServer::body_get_param);
|
ObjectTypeDB::bind_method(_MD("body_get_param","body","param"),&Physics2DServer::body_get_param);
|
||||||
|
|
||||||
ObjectTypeDB::bind_method(_MD("body_static_simulate_motion","body","new_xform"),&Physics2DServer::body_static_simulate_motion);
|
|
||||||
|
|
||||||
ObjectTypeDB::bind_method(_MD("body_set_state","body","state","value"),&Physics2DServer::body_set_state);
|
ObjectTypeDB::bind_method(_MD("body_set_state","body","state","value"),&Physics2DServer::body_set_state);
|
||||||
ObjectTypeDB::bind_method(_MD("body_get_state","body","state"),&Physics2DServer::body_get_state);
|
ObjectTypeDB::bind_method(_MD("body_get_state","body","state"),&Physics2DServer::body_get_state);
|
||||||
|
|
||||||
|
@ -371,7 +398,7 @@ void Physics2DServer::_bind_methods() {
|
||||||
BIND_CONSTANT( AREA_SPACE_OVERRIDE_REPLACE );
|
BIND_CONSTANT( AREA_SPACE_OVERRIDE_REPLACE );
|
||||||
|
|
||||||
BIND_CONSTANT( BODY_MODE_STATIC );
|
BIND_CONSTANT( BODY_MODE_STATIC );
|
||||||
BIND_CONSTANT( BODY_MODE_STATIC_ACTIVE );
|
BIND_CONSTANT( BODY_MODE_KINEMATIC );
|
||||||
BIND_CONSTANT( BODY_MODE_RIGID );
|
BIND_CONSTANT( BODY_MODE_RIGID );
|
||||||
BIND_CONSTANT( BODY_MODE_CHARACTER );
|
BIND_CONSTANT( BODY_MODE_CHARACTER );
|
||||||
|
|
||||||
|
@ -394,6 +421,10 @@ void Physics2DServer::_bind_methods() {
|
||||||
BIND_CONSTANT( DAMPED_STRING_STIFFNESS );
|
BIND_CONSTANT( DAMPED_STRING_STIFFNESS );
|
||||||
BIND_CONSTANT( DAMPED_STRING_DAMPING );
|
BIND_CONSTANT( DAMPED_STRING_DAMPING );
|
||||||
|
|
||||||
|
BIND_CONSTANT( CCD_MODE_DISABLED );
|
||||||
|
BIND_CONSTANT( CCD_MODE_CAST_RAY );
|
||||||
|
BIND_CONSTANT( CCD_MODE_CAST_SHAPE );
|
||||||
|
|
||||||
// BIND_CONSTANT( TYPE_BODY );
|
// BIND_CONSTANT( TYPE_BODY );
|
||||||
// BIND_CONSTANT( TYPE_AREA );
|
// BIND_CONSTANT( TYPE_AREA );
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,7 @@ class Physics2DDirectSpaceState : public Object {
|
||||||
|
|
||||||
Variant _intersect_ray(const Vector2& p_from, const Vector2& p_to,const Vector<RID>& p_exclude=Vector<RID>(),uint32_t p_user_mask=0);
|
Variant _intersect_ray(const Vector2& p_from, const Vector2& p_to,const Vector<RID>& p_exclude=Vector<RID>(),uint32_t p_user_mask=0);
|
||||||
Variant _intersect_shape(const RID& p_shape, const Matrix32& p_xform,int p_result_max=64,const Vector<RID>& p_exclude=Vector<RID>(),uint32_t p_user_mask=0);
|
Variant _intersect_shape(const RID& p_shape, const Matrix32& p_xform,int p_result_max=64,const Vector<RID>& p_exclude=Vector<RID>(),uint32_t p_user_mask=0);
|
||||||
|
Variant _cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,const Vector<RID>& p_exclude=Vector<RID>(),uint32_t p_user_mask=0);
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -118,7 +119,26 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual int intersect_shape(const RID& p_shape, const Matrix32& p_xform,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_user_mask=0)=0;
|
virtual int intersect_shape(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_user_mask=0)=0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct MotionCastCollision {
|
||||||
|
|
||||||
|
float travel; //0 to 1, if 0 then it's blocked
|
||||||
|
Vector2 point;
|
||||||
|
Vector2 normal;
|
||||||
|
RID rid;
|
||||||
|
ObjectID collider_id;
|
||||||
|
Object *collider;
|
||||||
|
int shape;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual bool cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion, MotionCastCollision &r_result, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_user_mask=0)=0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Physics2DDirectSpaceState();
|
Physics2DDirectSpaceState();
|
||||||
};
|
};
|
||||||
|
@ -179,6 +199,8 @@ public:
|
||||||
virtual Variant shape_get_data(RID p_shape) const=0;
|
virtual Variant shape_get_data(RID p_shape) const=0;
|
||||||
virtual real_t shape_get_custom_solver_bias(RID p_shape) const=0;
|
virtual real_t shape_get_custom_solver_bias(RID p_shape) const=0;
|
||||||
|
|
||||||
|
//these work well, but should be used from the main thread only
|
||||||
|
virtual bool shape_collide(RID p_shape_A, const Matrix32& p_xform_A,const Vector2& p_motion_A,RID p_shape_B, const Matrix32& p_xform_B, const Vector2& p_motion_B,Vector2 *r_results,int p_result_max,int &r_result_count)=0;
|
||||||
|
|
||||||
/* SPACE API */
|
/* SPACE API */
|
||||||
|
|
||||||
|
@ -265,10 +287,10 @@ public:
|
||||||
|
|
||||||
enum BodyMode {
|
enum BodyMode {
|
||||||
BODY_MODE_STATIC,
|
BODY_MODE_STATIC,
|
||||||
BODY_MODE_STATIC_ACTIVE,
|
BODY_MODE_KINEMATIC,
|
||||||
BODY_MODE_RIGID,
|
BODY_MODE_RIGID,
|
||||||
//BODY_MODE_SOFT
|
|
||||||
BODY_MODE_CHARACTER
|
BODY_MODE_CHARACTER
|
||||||
|
//BODY_MODE_SOFT ??
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual RID body_create(BodyMode p_mode=BODY_MODE_RIGID,bool p_init_sleeping=false)=0;
|
virtual RID body_create(BodyMode p_mode=BODY_MODE_RIGID,bool p_init_sleeping=false)=0;
|
||||||
|
@ -277,7 +299,7 @@ public:
|
||||||
virtual RID body_get_space(RID p_body) const=0;
|
virtual RID body_get_space(RID p_body) const=0;
|
||||||
|
|
||||||
virtual void body_set_mode(RID p_body, BodyMode p_mode)=0;
|
virtual void body_set_mode(RID p_body, BodyMode p_mode)=0;
|
||||||
virtual BodyMode body_get_mode(RID p_body, BodyMode p_mode) const=0;
|
virtual BodyMode body_get_mode(RID p_body) const=0;
|
||||||
|
|
||||||
virtual void body_add_shape(RID p_body, RID p_shape, const Matrix32& p_transform=Matrix32())=0;
|
virtual void body_add_shape(RID p_body, RID p_shape, const Matrix32& p_transform=Matrix32())=0;
|
||||||
virtual void body_set_shape(RID p_body, int p_shape_idx,RID p_shape)=0;
|
virtual void body_set_shape(RID p_body, int p_shape_idx,RID p_shape)=0;
|
||||||
|
@ -296,8 +318,14 @@ public:
|
||||||
virtual void body_attach_object_instance_ID(RID p_body,uint32_t p_ID)=0;
|
virtual void body_attach_object_instance_ID(RID p_body,uint32_t p_ID)=0;
|
||||||
virtual uint32_t body_get_object_instance_ID(RID p_body) const=0;
|
virtual uint32_t body_get_object_instance_ID(RID p_body) const=0;
|
||||||
|
|
||||||
virtual void body_set_enable_continuous_collision_detection(RID p_body,bool p_enable)=0;
|
enum CCDMode {
|
||||||
virtual bool body_is_continuous_collision_detection_enabled(RID p_body) const=0;
|
CCD_MODE_DISABLED,
|
||||||
|
CCD_MODE_CAST_RAY,
|
||||||
|
CCD_MODE_CAST_SHAPE,
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void body_set_continuous_collision_detection_mode(RID p_body,CCDMode p_mode)=0;
|
||||||
|
virtual CCDMode body_get_continuous_collision_detection_mode(RID p_body) const=0;
|
||||||
|
|
||||||
virtual void body_set_user_flags(RID p_body, uint32_t p_flags)=0;
|
virtual void body_set_user_flags(RID p_body, uint32_t p_flags)=0;
|
||||||
virtual uint32_t body_get_user_flags(RID p_body, uint32_t p_flags) const=0;
|
virtual uint32_t body_get_user_flags(RID p_body, uint32_t p_flags) const=0;
|
||||||
|
@ -313,8 +341,6 @@ public:
|
||||||
virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value)=0;
|
virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value)=0;
|
||||||
virtual float body_get_param(RID p_body, BodyParameter p_param) const=0;
|
virtual float body_get_param(RID p_body, BodyParameter p_param) const=0;
|
||||||
|
|
||||||
//advanced simulation
|
|
||||||
virtual void body_static_simulate_motion(RID p_body,const Matrix32& p_new_transform)=0;
|
|
||||||
|
|
||||||
//state
|
//state
|
||||||
enum BodyState {
|
enum BodyState {
|
||||||
|
@ -355,6 +381,8 @@ public:
|
||||||
|
|
||||||
virtual void body_set_force_integration_callback(RID p_body,Object *p_receiver,const StringName& p_method,const Variant& p_udata=Variant())=0;
|
virtual void body_set_force_integration_callback(RID p_body,Object *p_receiver,const StringName& p_method,const Variant& p_udata=Variant())=0;
|
||||||
|
|
||||||
|
virtual bool body_collide_shape(RID p_body, int p_body_shape,RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count)=0;
|
||||||
|
|
||||||
/* JOINT API */
|
/* JOINT API */
|
||||||
|
|
||||||
enum JointType {
|
enum JointType {
|
||||||
|
@ -417,6 +445,7 @@ VARIANT_ENUM_CAST( Physics2DServer::AreaSpaceOverrideMode );
|
||||||
VARIANT_ENUM_CAST( Physics2DServer::BodyMode );
|
VARIANT_ENUM_CAST( Physics2DServer::BodyMode );
|
||||||
VARIANT_ENUM_CAST( Physics2DServer::BodyParameter );
|
VARIANT_ENUM_CAST( Physics2DServer::BodyParameter );
|
||||||
VARIANT_ENUM_CAST( Physics2DServer::BodyState );
|
VARIANT_ENUM_CAST( Physics2DServer::BodyState );
|
||||||
|
VARIANT_ENUM_CAST( Physics2DServer::CCDMode );
|
||||||
VARIANT_ENUM_CAST( Physics2DServer::JointParam );
|
VARIANT_ENUM_CAST( Physics2DServer::JointParam );
|
||||||
VARIANT_ENUM_CAST( Physics2DServer::JointType );
|
VARIANT_ENUM_CAST( Physics2DServer::JointType );
|
||||||
VARIANT_ENUM_CAST( Physics2DServer::DampedStringParam );
|
VARIANT_ENUM_CAST( Physics2DServer::DampedStringParam );
|
||||||
|
|
|
@ -374,7 +374,7 @@ void PhysicsServer::_bind_methods() {
|
||||||
BIND_CONSTANT( AREA_SPACE_OVERRIDE_REPLACE );
|
BIND_CONSTANT( AREA_SPACE_OVERRIDE_REPLACE );
|
||||||
|
|
||||||
BIND_CONSTANT( BODY_MODE_STATIC );
|
BIND_CONSTANT( BODY_MODE_STATIC );
|
||||||
BIND_CONSTANT( BODY_MODE_STATIC_ACTIVE );
|
BIND_CONSTANT( BODY_MODE_KINEMATIC );
|
||||||
BIND_CONSTANT( BODY_MODE_RIGID );
|
BIND_CONSTANT( BODY_MODE_RIGID );
|
||||||
BIND_CONSTANT( BODY_MODE_CHARACTER );
|
BIND_CONSTANT( BODY_MODE_CHARACTER );
|
||||||
|
|
||||||
|
|
|
@ -268,7 +268,7 @@ public:
|
||||||
|
|
||||||
enum BodyMode {
|
enum BodyMode {
|
||||||
BODY_MODE_STATIC,
|
BODY_MODE_STATIC,
|
||||||
BODY_MODE_STATIC_ACTIVE,
|
BODY_MODE_KINEMATIC,
|
||||||
BODY_MODE_RIGID,
|
BODY_MODE_RIGID,
|
||||||
//BODY_MODE_SOFT
|
//BODY_MODE_SOFT
|
||||||
BODY_MODE_CHARACTER
|
BODY_MODE_CHARACTER
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -82,8 +82,6 @@
|
||||||
#include "plugins/path_2d_editor_plugin.h"
|
#include "plugins/path_2d_editor_plugin.h"
|
||||||
#include "plugins/particles_editor_plugin.h"
|
#include "plugins/particles_editor_plugin.h"
|
||||||
#include "plugins/particles_2d_editor_plugin.h"
|
#include "plugins/particles_2d_editor_plugin.h"
|
||||||
#include "plugins/font_editor_plugin.h"
|
|
||||||
#include "plugins/animation_editor_plugin.h"
|
|
||||||
#include "plugins/animation_tree_editor_plugin.h"
|
#include "plugins/animation_tree_editor_plugin.h"
|
||||||
#include "plugins/tile_set_editor_plugin.h"
|
#include "plugins/tile_set_editor_plugin.h"
|
||||||
#include "plugins/animation_player_editor_plugin.h"
|
#include "plugins/animation_player_editor_plugin.h"
|
||||||
|
@ -94,6 +92,7 @@
|
||||||
#include "tools/editor/io_plugins/editor_sample_import_plugin.h"
|
#include "tools/editor/io_plugins/editor_sample_import_plugin.h"
|
||||||
#include "tools/editor/io_plugins/editor_translation_import_plugin.h"
|
#include "tools/editor/io_plugins/editor_translation_import_plugin.h"
|
||||||
|
|
||||||
|
|
||||||
EditorNode *EditorNode::singleton=NULL;
|
EditorNode *EditorNode::singleton=NULL;
|
||||||
|
|
||||||
void EditorNode::_update_title() {
|
void EditorNode::_update_title() {
|
||||||
|
@ -2130,9 +2129,28 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
|
||||||
} break;
|
} break;
|
||||||
case RUN_SETTINGS: {
|
case RUN_SETTINGS: {
|
||||||
|
|
||||||
|
|
||||||
project_settings->popup_project_settings();
|
project_settings->popup_project_settings();
|
||||||
} break;
|
} break;
|
||||||
|
case RUN_PROJECT_MANAGER: {
|
||||||
|
|
||||||
|
if (!p_confirmed) {
|
||||||
|
confirmation->get_ok()->set_text("Yes");
|
||||||
|
confirmation->set_text("Open Project Manager? \n(Unsaved changes will be lost)");
|
||||||
|
confirmation->popup_centered(Size2(300,70));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
get_scene()->quit();
|
||||||
|
String exec = OS::get_singleton()->get_executable_path();
|
||||||
|
|
||||||
|
List<String> args;
|
||||||
|
args.push_back ( "-path" );
|
||||||
|
args.push_back (exec.get_base_dir() );
|
||||||
|
|
||||||
|
OS::ProcessID pid=0;
|
||||||
|
Error err = OS::get_singleton()->execute(exec,args,false,&pid);
|
||||||
|
ERR_FAIL_COND(err);
|
||||||
|
} break;
|
||||||
case RUN_FILE_SERVER: {
|
case RUN_FILE_SERVER: {
|
||||||
|
|
||||||
//file_server
|
//file_server
|
||||||
|
@ -3407,6 +3425,7 @@ EditorNode::EditorNode() {
|
||||||
p->add_item("Redo",EDIT_REDO,KEY_MASK_CMD+KEY_MASK_SHIFT+KEY_Z);
|
p->add_item("Redo",EDIT_REDO,KEY_MASK_CMD+KEY_MASK_SHIFT+KEY_Z);
|
||||||
p->add_separator();
|
p->add_separator();
|
||||||
p->add_item("Project Settings",RUN_SETTINGS);
|
p->add_item("Project Settings",RUN_SETTINGS);
|
||||||
|
p->add_item("Project Manager",RUN_PROJECT_MANAGER);
|
||||||
p->add_separator();
|
p->add_separator();
|
||||||
p->add_item("Quit",FILE_QUIT,KEY_MASK_CMD+KEY_Q);
|
p->add_item("Quit",FILE_QUIT,KEY_MASK_CMD+KEY_Q);
|
||||||
|
|
||||||
|
@ -3959,16 +3978,13 @@ EditorNode::EditorNode() {
|
||||||
add_editor_plugin( memnew( ScriptEditorPlugin(this) ) );
|
add_editor_plugin( memnew( ScriptEditorPlugin(this) ) );
|
||||||
add_editor_plugin( memnew( EditorHelpPlugin(this) ) );
|
add_editor_plugin( memnew( EditorHelpPlugin(this) ) );
|
||||||
add_editor_plugin( memnew( AnimationPlayerEditorPlugin(this) ) );
|
add_editor_plugin( memnew( AnimationPlayerEditorPlugin(this) ) );
|
||||||
//add_editor_plugin( memnew( AnimationEditorPlugin(this) ) ); - not useful anymore
|
|
||||||
add_editor_plugin( memnew( ShaderEditorPlugin(this) ) );
|
add_editor_plugin( memnew( ShaderEditorPlugin(this) ) );
|
||||||
add_editor_plugin( memnew( CameraEditorPlugin(this) ) );
|
add_editor_plugin( memnew( CameraEditorPlugin(this) ) );
|
||||||
//add_editor_plugin( memnew( FontEditorPlugin(this) ) ); obsolete
|
|
||||||
add_editor_plugin( memnew( SampleEditorPlugin(this) ) );
|
add_editor_plugin( memnew( SampleEditorPlugin(this) ) );
|
||||||
add_editor_plugin( memnew( SampleLibraryEditorPlugin(this) ) );
|
add_editor_plugin( memnew( SampleLibraryEditorPlugin(this) ) );
|
||||||
add_editor_plugin( memnew( ThemeEditorPlugin(this) ) );
|
add_editor_plugin( memnew( ThemeEditorPlugin(this) ) );
|
||||||
add_editor_plugin( memnew( MultiMeshEditorPlugin(this) ) );
|
add_editor_plugin( memnew( MultiMeshEditorPlugin(this) ) );
|
||||||
add_editor_plugin( memnew( AnimationTreeEditorPlugin(this) ) );
|
add_editor_plugin( memnew( AnimationTreeEditorPlugin(this) ) );
|
||||||
//add_editor_plugin( memnew( GridMapEditorPlugin(this) ) );
|
|
||||||
add_editor_plugin( memnew( SamplePlayerEditorPlugin(this) ) );
|
add_editor_plugin( memnew( SamplePlayerEditorPlugin(this) ) );
|
||||||
add_editor_plugin( memnew( MeshLibraryEditorPlugin(this) ) );
|
add_editor_plugin( memnew( MeshLibraryEditorPlugin(this) ) );
|
||||||
add_editor_plugin( memnew( StreamEditorPlugin(this) ) );
|
add_editor_plugin( memnew( StreamEditorPlugin(this) ) );
|
||||||
|
|
|
@ -137,6 +137,7 @@ class EditorNode : public Node {
|
||||||
RUN_PLAY_CUSTOM_SCENE,
|
RUN_PLAY_CUSTOM_SCENE,
|
||||||
RUN_SCENE_SETTINGS,
|
RUN_SCENE_SETTINGS,
|
||||||
RUN_SETTINGS,
|
RUN_SETTINGS,
|
||||||
|
RUN_PROJECT_MANAGER,
|
||||||
RUN_FILE_SERVER,
|
RUN_FILE_SERVER,
|
||||||
RUN_DEPLOY_DUMB_CLIENTS,
|
RUN_DEPLOY_DUMB_CLIENTS,
|
||||||
SETTINGS_UPDATE_ALWAYS,
|
SETTINGS_UPDATE_ALWAYS,
|
||||||
|
|
|
@ -150,6 +150,11 @@ void EditorImportTextureOptions::_notification(int p_what) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditorImportTextureOptions::show_2d_notice() {
|
||||||
|
|
||||||
|
notice_for_2d->show();
|
||||||
|
}
|
||||||
|
|
||||||
EditorImportTextureOptions::EditorImportTextureOptions() {
|
EditorImportTextureOptions::EditorImportTextureOptions() {
|
||||||
|
|
||||||
|
|
||||||
|
@ -206,6 +211,14 @@ EditorImportTextureOptions::EditorImportTextureOptions() {
|
||||||
|
|
||||||
|
|
||||||
add_margin_child("Texture Options",flags,true);
|
add_margin_child("Texture Options",flags,true);
|
||||||
|
|
||||||
|
notice_for_2d = memnew( Label );
|
||||||
|
notice_for_2d->set_text("NOTICE: You are not forced to import textures for 2D projects. Just copy your .jpg or .png files to your project, and change export options later. Atlases can be generated on export too.");
|
||||||
|
notice_for_2d->set_custom_minimum_size(Size2(0,50));
|
||||||
|
notice_for_2d->set_autowrap(true);
|
||||||
|
add_child(notice_for_2d);
|
||||||
|
notice_for_2d->hide();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
|
@ -530,6 +543,7 @@ EditorTextureImportDialog::EditorTextureImportDialog(EditorTextureImportPlugin*
|
||||||
texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA|EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS|EditorTextureImportPlugin::IMAGE_FLAG_FILTER);
|
texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA|EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS|EditorTextureImportPlugin::IMAGE_FLAG_FILTER);
|
||||||
texture_options->set_quality(0.7);
|
texture_options->set_quality(0.7);
|
||||||
texture_options->set_format(EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY);
|
texture_options->set_format(EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY);
|
||||||
|
texture_options->show_2d_notice();
|
||||||
set_title("Import Textures for Atlas (2D)");
|
set_title("Import Textures for Atlas (2D)");
|
||||||
|
|
||||||
} else if (p_2d) {
|
} else if (p_2d) {
|
||||||
|
@ -537,6 +551,7 @@ EditorTextureImportDialog::EditorTextureImportDialog(EditorTextureImportPlugin*
|
||||||
texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS|EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA|EditorTextureImportPlugin::IMAGE_FLAG_FILTER);
|
texture_options->set_flags(EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS|EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA|EditorTextureImportPlugin::IMAGE_FLAG_FILTER);
|
||||||
texture_options->set_quality(0.7);
|
texture_options->set_quality(0.7);
|
||||||
texture_options->set_format(EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY);
|
texture_options->set_format(EditorTextureImportPlugin::IMAGE_FORMAT_COMPRESS_DISK_LOSSY);
|
||||||
|
texture_options->show_2d_notice();
|
||||||
set_title("Import Textures for 2D");
|
set_title("Import Textures for 2D");
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|
|
@ -116,6 +116,7 @@ class EditorImportTextureOptions : public VBoxContainer {
|
||||||
HSlider *quality;
|
HSlider *quality;
|
||||||
Tree *flags;
|
Tree *flags;
|
||||||
Vector<TreeItem*> items;
|
Vector<TreeItem*> items;
|
||||||
|
Label *notice_for_2d;
|
||||||
|
|
||||||
bool updating;
|
bool updating;
|
||||||
|
|
||||||
|
@ -140,6 +141,8 @@ public:
|
||||||
void set_quality(float p_quality);
|
void set_quality(float p_quality);
|
||||||
float get_quality() const;
|
float get_quality() const;
|
||||||
|
|
||||||
|
void show_2d_notice();
|
||||||
|
|
||||||
EditorImportTextureOptions();
|
EditorImportTextureOptions();
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,806 +0,0 @@
|
||||||
/*************************************************************************/
|
|
||||||
/* animation_editor_plugin.cpp */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* 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. */
|
|
||||||
/*************************************************************************/
|
|
||||||
#include "animation_editor_plugin.h"
|
|
||||||
#include "io/resource_loader.h"
|
|
||||||
|
|
||||||
|
|
||||||
class AnimationEditor_TrackEditor : public Object {
|
|
||||||
|
|
||||||
OBJ_TYPE(AnimationEditor_TrackEditor,Object);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
bool _set(const StringName& p_name, const Variant& p_value) {
|
|
||||||
|
|
||||||
if (anim.is_null())
|
|
||||||
return false;
|
|
||||||
String name=p_name;
|
|
||||||
|
|
||||||
if (name=="track/interpolation") {
|
|
||||||
|
|
||||||
anim_editor->_internal_set_interpolation_type(track,Animation::InterpolationType(p_value.operator int()));
|
|
||||||
|
|
||||||
} else if (name.begins_with("keys/")) {
|
|
||||||
|
|
||||||
int key = name.get_slice("/",1).to_int();
|
|
||||||
ERR_FAIL_INDEX_V( key,anim->track_get_key_count(track), false );
|
|
||||||
String what = name.get_slice("/",2);
|
|
||||||
float time = anim->track_get_key_time(track,key);
|
|
||||||
float transition = anim->track_get_key_transition(track,key);
|
|
||||||
|
|
||||||
if (what=="time") {
|
|
||||||
Variant v = anim->track_get_key_value(track,key);
|
|
||||||
anim_editor->_internal_set_key(track,time,transition,v);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (what=="transition") {
|
|
||||||
transition=p_value;
|
|
||||||
Variant v = anim->track_get_key_value(track,key);
|
|
||||||
anim_editor->_internal_set_key(track,time,transition,v);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(anim->track_get_type(track)) {
|
|
||||||
|
|
||||||
case Animation::TYPE_TRANSFORM: {
|
|
||||||
|
|
||||||
Vector3 scale,loc;
|
|
||||||
Quat rot;
|
|
||||||
anim->transform_track_get_key(track,key,&loc,&rot,&scale);
|
|
||||||
|
|
||||||
|
|
||||||
if (what=="loc") {
|
|
||||||
loc=p_value;
|
|
||||||
} else if (what=="scale") {
|
|
||||||
scale=p_value;
|
|
||||||
} else if (what=="rot") {
|
|
||||||
rot=p_value;
|
|
||||||
} else {
|
|
||||||
return false; //meh
|
|
||||||
}
|
|
||||||
|
|
||||||
Dictionary k;
|
|
||||||
k["rot"]=rot;
|
|
||||||
k["loc"]=loc;
|
|
||||||
k["scale"]=scale;
|
|
||||||
anim_editor->_internal_set_key(track,time,transition,k);
|
|
||||||
|
|
||||||
} break;
|
|
||||||
case Animation::TYPE_METHOD: {
|
|
||||||
|
|
||||||
} break;
|
|
||||||
case Animation::TYPE_VALUE: {
|
|
||||||
|
|
||||||
if (what=="value")
|
|
||||||
anim_editor->_internal_set_key(track,time,transition,p_value);
|
|
||||||
} break;
|
|
||||||
default: { return false; }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _get(const StringName& p_name,Variant &r_ret) const {
|
|
||||||
|
|
||||||
if (anim.is_null())
|
|
||||||
return false;
|
|
||||||
String name=p_name;
|
|
||||||
|
|
||||||
if (name=="track/interpolation") {
|
|
||||||
|
|
||||||
r_ret=anim->track_get_interpolation_type(track);
|
|
||||||
|
|
||||||
} else if (name.begins_with("keys/")) {
|
|
||||||
|
|
||||||
int key = name.get_slice("/",1).to_int();
|
|
||||||
ERR_FAIL_INDEX_V( key,anim->track_get_key_count(track), Variant() );
|
|
||||||
String what = name.get_slice("/",2);
|
|
||||||
|
|
||||||
if (what=="time") {
|
|
||||||
r_ret=anim->track_get_key_time(track,key);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (what=="transition") {
|
|
||||||
r_ret=anim->track_get_key_transition(track,key);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(anim->track_get_type(track)) {
|
|
||||||
|
|
||||||
case Animation::TYPE_TRANSFORM: {
|
|
||||||
|
|
||||||
Vector3 scale,loc;
|
|
||||||
Quat rot;
|
|
||||||
anim->transform_track_get_key(track,key,&loc,&rot,&scale);
|
|
||||||
|
|
||||||
|
|
||||||
if (what=="loc") {
|
|
||||||
r_ret= loc;
|
|
||||||
} else if (what=="scale") {
|
|
||||||
r_ret= scale;
|
|
||||||
} else if (what=="rot") {
|
|
||||||
r_ret= rot;
|
|
||||||
}
|
|
||||||
|
|
||||||
} break;
|
|
||||||
case Animation::TYPE_METHOD: {
|
|
||||||
|
|
||||||
} break;
|
|
||||||
case Animation::TYPE_VALUE: {
|
|
||||||
|
|
||||||
if (what=="value")
|
|
||||||
r_ret= anim->track_get_key_value(track,key);
|
|
||||||
} break;
|
|
||||||
default: { return false; }
|
|
||||||
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
void _get_property_list( List<PropertyInfo> *p_list) const {
|
|
||||||
|
|
||||||
p_list->push_back(PropertyInfo(Variant::INT,"track/interpolation",PROPERTY_HINT_ENUM,"Nearest,Linear,Cubic") );
|
|
||||||
|
|
||||||
if (anim.is_null())
|
|
||||||
return;
|
|
||||||
|
|
||||||
int keycount = anim->track_get_key_count(track);
|
|
||||||
|
|
||||||
for(int i=0;i<keycount;i++) {
|
|
||||||
|
|
||||||
p_list->push_back(PropertyInfo(Variant::REAL,"keys/"+itos(i)+"/time",PROPERTY_HINT_RANGE,"0,3600,0.001") );
|
|
||||||
p_list->push_back(PropertyInfo(Variant::REAL,"keys/"+itos(i)+"/transition",PROPERTY_HINT_EXP_EASING) );
|
|
||||||
switch(anim->track_get_type(track)) {
|
|
||||||
|
|
||||||
case Animation::TYPE_TRANSFORM: {
|
|
||||||
|
|
||||||
p_list->push_back(PropertyInfo(Variant::VECTOR3,"keys/"+itos(i)+"/loc" ) );
|
|
||||||
p_list->push_back(PropertyInfo(Variant::QUAT,"keys/"+itos(i)+"/rot" ) );
|
|
||||||
p_list->push_back(PropertyInfo(Variant::VECTOR3,"keys/"+itos(i)+"/scale" ) );
|
|
||||||
|
|
||||||
} break;
|
|
||||||
case Animation::TYPE_METHOD: {
|
|
||||||
|
|
||||||
} break;
|
|
||||||
case Animation::TYPE_VALUE: {
|
|
||||||
|
|
||||||
|
|
||||||
Variant v = anim->track_get_key_value(track,i);
|
|
||||||
|
|
||||||
PropertyHint hint=PROPERTY_HINT_NONE;
|
|
||||||
String hint_string;
|
|
||||||
if (v.get_type()==Variant::INT) {
|
|
||||||
hint=PROPERTY_HINT_RANGE;
|
|
||||||
hint_string="-16384,16384,1";
|
|
||||||
} else if (v.get_type()==Variant::REAL) {
|
|
||||||
hint=PROPERTY_HINT_RANGE;
|
|
||||||
hint_string="-16384,16384,0.001";
|
|
||||||
} else if (v.get_type()==Variant::OBJECT) {
|
|
||||||
hint=PROPERTY_HINT_RESOURCE_TYPE;
|
|
||||||
hint_string="Resource";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
p_list->push_back(PropertyInfo(v.get_type(),"keys/"+itos(i)+"/value",hint,hint_string ) );
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} break;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
AnimationEditor *anim_editor;
|
|
||||||
|
|
||||||
Ref<Animation> anim;
|
|
||||||
int track;
|
|
||||||
AnimationEditor_TrackEditor() { }
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
void AnimationEditor::update_anim() {
|
|
||||||
|
|
||||||
tracks->clear();
|
|
||||||
key_editor->edit(NULL);
|
|
||||||
TreeItem *root = tracks->create_item(NULL);
|
|
||||||
|
|
||||||
TreeItem *sel=NULL;
|
|
||||||
int selected_track=-1;
|
|
||||||
if (animation->has_meta("_anim_editor_selected_track_"))
|
|
||||||
selected_track=animation->get_meta("_anim_editor_selected_track_");
|
|
||||||
|
|
||||||
for(int i=0;i<animation->get_track_count();i++) {
|
|
||||||
|
|
||||||
String path = animation->track_get_path(i);
|
|
||||||
TreeItem *track = tracks->create_item(root);
|
|
||||||
track->set_text(0,itos(i));
|
|
||||||
track->set_editable(0,false);
|
|
||||||
track->set_text(1,path);
|
|
||||||
track->set_editable(1,true);
|
|
||||||
track->set_metadata(0,i);
|
|
||||||
if (selected_track==i)
|
|
||||||
sel=track;
|
|
||||||
|
|
||||||
switch(animation->track_get_type(i)) {
|
|
||||||
|
|
||||||
case Animation::TYPE_TRANSFORM: {
|
|
||||||
|
|
||||||
track->set_icon(0,get_icon("Matrix","EditorIcons"));
|
|
||||||
|
|
||||||
} break;
|
|
||||||
case Animation::TYPE_METHOD: {
|
|
||||||
track->set_icon(0,get_icon("TrackMethod","EditorIcons"));
|
|
||||||
} break;
|
|
||||||
case Animation::TYPE_VALUE: {
|
|
||||||
|
|
||||||
track->set_icon(0,get_icon("TrackValue","EditorIcons"));
|
|
||||||
} break;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sel) {
|
|
||||||
sel->select(1);
|
|
||||||
_update_track_keys();
|
|
||||||
} else {
|
|
||||||
selected_track=-1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimationEditor::_update_track_keys() {
|
|
||||||
if (selected_track<0 || selected_track>=animation->get_track_count())
|
|
||||||
return;
|
|
||||||
track_editor->anim=animation;
|
|
||||||
track_editor->track=selected_track;
|
|
||||||
key_editor->edit(NULL);
|
|
||||||
key_editor->edit(track_editor);
|
|
||||||
|
|
||||||
if (animation->track_get_type(selected_track)==Animation::TYPE_VALUE) {
|
|
||||||
key_time->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,160);
|
|
||||||
key_type->show();
|
|
||||||
} else {
|
|
||||||
key_time->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,60);
|
|
||||||
key_type->hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimationEditor::_track_path_changed() {
|
|
||||||
|
|
||||||
TreeItem *ti=tracks->get_edited();
|
|
||||||
int track=ti->get_metadata(0);
|
|
||||||
String path=ti->get_text(1);
|
|
||||||
if (track<0 || track>=animation->get_track_count())
|
|
||||||
return;
|
|
||||||
undo_redo->create_action("Create Anim Track");
|
|
||||||
undo_redo->add_do_method(animation.ptr(),"track_set_path",track,path);
|
|
||||||
undo_redo->add_undo_method(animation.ptr(),"track_set_path",track,animation->track_get_path(track));
|
|
||||||
undo_redo->add_do_method(this,"_internal_check_update",animation);
|
|
||||||
undo_redo->add_undo_method(this,"_internal_check_update",animation);
|
|
||||||
undo_redo->commit_action();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimationEditor::_track_selected() {
|
|
||||||
|
|
||||||
TreeItem *ti=tracks->get_selected();
|
|
||||||
if(!ti)
|
|
||||||
return;
|
|
||||||
selected_track=ti->get_metadata(0);
|
|
||||||
animation->set_meta("_anim_editor_selected_track_",selected_track);
|
|
||||||
_update_track_keys();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimationEditor::_track_added() {
|
|
||||||
|
|
||||||
undo_redo->create_action("Create Anim Track");
|
|
||||||
undo_redo->add_do_method(animation.ptr(),"add_track",track_type->get_selected(),-1);
|
|
||||||
undo_redo->add_undo_method(animation.ptr(),"remove_track",animation->get_track_count());
|
|
||||||
undo_redo->add_do_method(this,"_internal_set_selected_track",animation->get_track_count(),animation);
|
|
||||||
undo_redo->add_undo_method(this,"_internal_set_selected_track",selected_track,animation);
|
|
||||||
undo_redo->add_do_method(this,"_internal_check_update",animation);
|
|
||||||
undo_redo->add_undo_method(this,"_internal_check_update",animation);
|
|
||||||
undo_redo->commit_action();
|
|
||||||
update_anim();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimationEditor::_track_removed() {
|
|
||||||
|
|
||||||
if (selected_track<0 || selected_track>=animation->get_track_count())
|
|
||||||
return;
|
|
||||||
|
|
||||||
undo_redo->create_action("Remove Anim Track");
|
|
||||||
undo_redo->add_do_method(animation.ptr(),"remove_track",selected_track);
|
|
||||||
undo_redo->add_undo_method(animation.ptr(),"add_track",animation->track_get_type(selected_track),selected_track);
|
|
||||||
undo_redo->add_undo_method(animation.ptr(),"track_set_path",selected_track,animation->track_get_path(selected_track));
|
|
||||||
//todo interpolation
|
|
||||||
for(int i=0;i<animation->track_get_key_count(selected_track);i++) {
|
|
||||||
|
|
||||||
Variant v = animation->track_get_key_value(selected_track,i);
|
|
||||||
float time = animation->track_get_key_time(selected_track,i);
|
|
||||||
|
|
||||||
undo_redo->add_undo_method(animation.ptr(),"track_insert_key",selected_track,time,v);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int old_track=selected_track;
|
|
||||||
if (selected_track>0)
|
|
||||||
selected_track--;
|
|
||||||
if (selected_track<0 || selected_track>=(animation->get_track_count()-1))
|
|
||||||
selected_track=-1;
|
|
||||||
|
|
||||||
undo_redo->add_do_method(this,"_internal_set_selected_track",selected_track,animation);
|
|
||||||
undo_redo->add_undo_method(this,"_internal_set_selected_track",old_track,animation);
|
|
||||||
|
|
||||||
undo_redo->add_do_method(this,"_internal_check_update",animation);
|
|
||||||
undo_redo->add_undo_method(this,"_internal_check_update",animation);
|
|
||||||
undo_redo->commit_action();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimationEditor::_internal_set_interpolation_type(int p_track,Animation::InterpolationType p_type) {
|
|
||||||
|
|
||||||
undo_redo->create_action("Set Interpolation");
|
|
||||||
undo_redo->add_do_method(animation.ptr(),"track_set_interpolation_type",p_track,p_type);
|
|
||||||
undo_redo->add_undo_method(animation.ptr(),"track_set_interpolation_type",p_track,animation->track_get_interpolation_type(p_track));
|
|
||||||
undo_redo->add_do_method(this,"_internal_set_selected_track",selected_track,animation);
|
|
||||||
undo_redo->add_undo_method(this,"_internal_set_selected_track",selected_track,animation);
|
|
||||||
undo_redo->add_do_method(this,"_internal_check_update",animation);
|
|
||||||
undo_redo->add_undo_method(this,"_internal_check_update",animation);
|
|
||||||
undo_redo->commit_action();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimationEditor::_internal_set_selected_track(int p_which,const Ref<Animation>& p_anim) {
|
|
||||||
|
|
||||||
if (is_visible() && animation==p_anim) {
|
|
||||||
selected_track=p_which;
|
|
||||||
animation->set_meta("_anim_editor_selected_track_",selected_track);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimationEditor::_track_moved_up() {
|
|
||||||
|
|
||||||
|
|
||||||
if (selected_track<0 || selected_track>=animation->get_track_count())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (selected_track<(animation->get_track_count()-1)) {
|
|
||||||
undo_redo->create_action("Move Up Track");
|
|
||||||
undo_redo->add_do_method(animation.ptr(),"track_move_up",selected_track);
|
|
||||||
undo_redo->add_undo_method(animation.ptr(),"track_move_down",selected_track+1);
|
|
||||||
undo_redo->add_do_method(this,"_internal_set_selected_track",selected_track+1,animation);
|
|
||||||
undo_redo->add_undo_method(this,"_internal_set_selected_track",selected_track,animation);
|
|
||||||
undo_redo->add_do_method(this,"_internal_check_update",animation);
|
|
||||||
undo_redo->add_undo_method(this,"_internal_check_update",animation);
|
|
||||||
undo_redo->commit_action();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimationEditor::_track_moved_down() {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (selected_track<0 || selected_track>=animation->get_track_count())
|
|
||||||
return;
|
|
||||||
if (selected_track>0) {
|
|
||||||
undo_redo->create_action("Move Down Track");
|
|
||||||
undo_redo->add_do_method(animation.ptr(),"track_move_down",selected_track);
|
|
||||||
undo_redo->add_undo_method(animation.ptr(),"track_move_up",selected_track-1);
|
|
||||||
undo_redo->add_do_method(this,"_internal_set_selected_track",selected_track-1,animation);
|
|
||||||
undo_redo->add_undo_method(this,"_internal_set_selected_track",selected_track,animation);
|
|
||||||
undo_redo->add_do_method(this,"_internal_check_update",animation);
|
|
||||||
undo_redo->add_undo_method(this,"_internal_check_update",animation);
|
|
||||||
undo_redo->commit_action();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimationEditor::_key_added() {
|
|
||||||
|
|
||||||
if (selected_track<0 || selected_track>=animation->get_track_count())
|
|
||||||
return;
|
|
||||||
|
|
||||||
bool need_variant= animation->track_get_type(selected_track)==Animation::TYPE_VALUE;
|
|
||||||
|
|
||||||
Variant v;
|
|
||||||
|
|
||||||
if (need_variant) {
|
|
||||||
|
|
||||||
switch(key_type->get_selected()) {
|
|
||||||
|
|
||||||
case Variant::NIL: v=Variant(); break;
|
|
||||||
case Variant::BOOL: v=false; break;
|
|
||||||
case Variant::INT: v=0; break;
|
|
||||||
case Variant::REAL: v=0.0; break;
|
|
||||||
case Variant::STRING: v=""; break;
|
|
||||||
case Variant::VECTOR2: v=Vector2(); break; // 5
|
|
||||||
case Variant::RECT2: v=Rect2(); break;
|
|
||||||
case Variant::VECTOR3: v=Vector3(); break;
|
|
||||||
case Variant::PLANE: v=Plane(); break;
|
|
||||||
case Variant::QUAT: v=Quat(); break;
|
|
||||||
case Variant::_AABB: v=AABB(); break; //sorry naming convention fail :( not like it's used often // 10
|
|
||||||
case Variant::MATRIX3: v=Matrix3(); break;
|
|
||||||
case Variant::TRANSFORM: v=Transform(); break;
|
|
||||||
case Variant::COLOR: v=Color(); break;
|
|
||||||
case Variant::IMAGE: v=Image(); break;
|
|
||||||
case Variant::NODE_PATH: v=NodePath(); break; // 15
|
|
||||||
case Variant::_RID: v=RID(); break;
|
|
||||||
case Variant::OBJECT: v=Variant(); break;
|
|
||||||
case Variant::INPUT_EVENT: v=InputEvent(); break;
|
|
||||||
case Variant::DICTIONARY: v=Dictionary(); break; // 20
|
|
||||||
case Variant::ARRAY: v=Array(); break;
|
|
||||||
case Variant::RAW_ARRAY: v=DVector<uint8_t>(); break;
|
|
||||||
case Variant::INT_ARRAY: v=DVector<int>(); break;
|
|
||||||
case Variant::REAL_ARRAY: v=DVector<real_t>(); break;
|
|
||||||
case Variant::STRING_ARRAY: v=DVector<String>(); break; //25
|
|
||||||
case Variant::VECTOR3_ARRAY: v=DVector<Vector3>(); break;
|
|
||||||
case Variant::COLOR_ARRAY: v=DVector<Color>(); break;
|
|
||||||
default: v=Variant(); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float time = key_time->get_text().to_double();
|
|
||||||
|
|
||||||
switch(animation->track_get_type(selected_track)) {
|
|
||||||
case Animation::TYPE_TRANSFORM: {
|
|
||||||
|
|
||||||
Dictionary d;
|
|
||||||
d["loc"]=Vector3();
|
|
||||||
d["rot"]=Quat();
|
|
||||||
d["scale"]=Vector3(1,1,1);
|
|
||||||
v=d;
|
|
||||||
|
|
||||||
} break;
|
|
||||||
case Animation::TYPE_VALUE: {
|
|
||||||
//v=v
|
|
||||||
} break;
|
|
||||||
case Animation::TYPE_METHOD: {
|
|
||||||
|
|
||||||
return; //not do anything yet
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
|
|
||||||
_internal_set_key(selected_track,time,1.0,v);
|
|
||||||
|
|
||||||
_update_track_keys();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void AnimationEditor::_internal_check_update(Ref<Animation> p_anim) {
|
|
||||||
|
|
||||||
if (is_visible() && p_anim==animation) {
|
|
||||||
update_anim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimationEditor::_internal_set_key(int p_track, float p_time, float p_transition,const Variant& p_value) {
|
|
||||||
|
|
||||||
int prev = animation->track_find_key(p_track,p_time);
|
|
||||||
bool existing = (prev>=0) && (animation->track_get_key_time(p_track,prev)==p_time);
|
|
||||||
|
|
||||||
undo_redo->create_action("Insert Key");
|
|
||||||
|
|
||||||
undo_redo->add_do_method(animation.ptr(),"track_insert_key",p_track,p_time,p_value,p_transition);
|
|
||||||
if (existing)
|
|
||||||
undo_redo->add_undo_method(animation.ptr(),"track_insert_key",p_track,p_time,animation->track_get_key_value(p_track,existing),animation->track_get_key_transition(p_track,existing));
|
|
||||||
else
|
|
||||||
undo_redo->add_undo_method(animation.ptr(),"track_remove_key",p_track,prev+1);
|
|
||||||
undo_redo->add_do_method(this,"_internal_check_update",animation);
|
|
||||||
undo_redo->add_undo_method(this,"_internal_check_update",animation);
|
|
||||||
|
|
||||||
undo_redo->commit_action();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimationEditor::_key_removed() {
|
|
||||||
|
|
||||||
if (selected_track<0 || selected_track>=animation->get_track_count())
|
|
||||||
return;
|
|
||||||
|
|
||||||
String sel=key_editor->get_selected_path();
|
|
||||||
if (sel.get_slice_count("/")<2)
|
|
||||||
return;
|
|
||||||
if (sel.get_slice("/",0)!="keys")
|
|
||||||
return;
|
|
||||||
int key = sel.get_slice("/",1).to_int();
|
|
||||||
if (key<0 || key>=animation->track_get_key_count(selected_track))
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
|
||||||
undo_redo->create_action("Remove Key");
|
|
||||||
|
|
||||||
Variant data = animation->track_get_key_value(selected_track,key);
|
|
||||||
float time = animation->track_get_key_time(selected_track,key);
|
|
||||||
undo_redo->add_do_method(animation.ptr(),"track_remove_key",selected_track,key);
|
|
||||||
undo_redo->add_undo_method(animation.ptr(),"track_insert_key",selected_track,time,data);
|
|
||||||
undo_redo->add_do_method(this,"_internal_check_update",animation);
|
|
||||||
undo_redo->add_undo_method(this,"_internal_check_update",animation);
|
|
||||||
undo_redo->commit_action();
|
|
||||||
|
|
||||||
_update_track_keys();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void AnimationEditor::edit(const Ref<Animation>& p_animation) {
|
|
||||||
|
|
||||||
|
|
||||||
animation=p_animation;
|
|
||||||
if (!animation.is_null())
|
|
||||||
update_anim();
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void AnimationEditor::_bind_methods() {
|
|
||||||
|
|
||||||
ObjectTypeDB::bind_method(_MD("_track_selected"),&AnimationEditor::_track_selected);
|
|
||||||
ObjectTypeDB::bind_method(_MD("_track_added"),&AnimationEditor::_track_added);
|
|
||||||
ObjectTypeDB::bind_method(_MD("_track_removed"),&AnimationEditor::_track_removed);
|
|
||||||
ObjectTypeDB::bind_method(_MD("_track_moved_up"),&AnimationEditor::_track_moved_up);
|
|
||||||
ObjectTypeDB::bind_method(_MD("_track_moved_down"),&AnimationEditor::_track_moved_down);
|
|
||||||
ObjectTypeDB::bind_method(_MD("_track_path_changed"),&AnimationEditor::_track_path_changed);
|
|
||||||
ObjectTypeDB::bind_method(_MD("_key_added"),&AnimationEditor::_key_added);
|
|
||||||
ObjectTypeDB::bind_method(_MD("_key_removed"),&AnimationEditor::_key_removed);
|
|
||||||
ObjectTypeDB::bind_method(_MD("_internal_check_update"),&AnimationEditor::_internal_check_update);
|
|
||||||
ObjectTypeDB::bind_method(_MD("_internal_set_selected_track"),&AnimationEditor::_internal_set_selected_track);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimationEditor::_notification(int p_what) {
|
|
||||||
|
|
||||||
switch(p_what) {
|
|
||||||
|
|
||||||
case NOTIFICATION_ENTER_SCENE: {
|
|
||||||
|
|
||||||
add_track->set_icon( get_icon("Add","EditorIcons") );
|
|
||||||
remove_track->set_icon( get_icon("Del","EditorIcons") );
|
|
||||||
move_up_track->set_icon( get_icon("Up","EditorIcons") );
|
|
||||||
move_down_track->set_icon( get_icon("Down","EditorIcons") );
|
|
||||||
time_icon->set_texture( get_icon("Time","EditorIcons") );
|
|
||||||
|
|
||||||
add_key->set_icon( get_icon("Add","EditorIcons") );
|
|
||||||
remove_key->set_icon( get_icon("Del","EditorIcons") );
|
|
||||||
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimationEditor::AnimationEditor() {
|
|
||||||
|
|
||||||
panel = memnew( Panel );
|
|
||||||
add_child(panel);
|
|
||||||
panel->set_area_as_parent_rect();
|
|
||||||
|
|
||||||
Control *left_pane = memnew( Control );
|
|
||||||
panel->add_child(left_pane);
|
|
||||||
left_pane->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_RATIO,0.5);
|
|
||||||
left_pane->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,0);
|
|
||||||
|
|
||||||
Label *l = memnew( Label );
|
|
||||||
l->set_text("Track List:");
|
|
||||||
l->set_pos(Point2(5,5));
|
|
||||||
left_pane->add_child(l);
|
|
||||||
|
|
||||||
/*
|
|
||||||
track_name = memnew( LineEdit );
|
|
||||||
track_name->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,10);
|
|
||||||
track_name->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,25);
|
|
||||||
track_name->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,80);
|
|
||||||
track_name->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_BEGIN,45);
|
|
||||||
left_pane->add_child(track_name);
|
|
||||||
*/
|
|
||||||
|
|
||||||
track_type = memnew( OptionButton );
|
|
||||||
track_type->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,10);
|
|
||||||
track_type->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,25);
|
|
||||||
track_type->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,115);
|
|
||||||
track_type->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_BEGIN,45);
|
|
||||||
left_pane->add_child(track_type);
|
|
||||||
track_type->add_item("Transform",Animation::TYPE_TRANSFORM);
|
|
||||||
track_type->add_item("Value",Animation::TYPE_VALUE);
|
|
||||||
track_type->add_item("Method",Animation::TYPE_METHOD);
|
|
||||||
|
|
||||||
|
|
||||||
add_track = memnew( Button );
|
|
||||||
add_track->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,110);
|
|
||||||
add_track->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,25);
|
|
||||||
add_track->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,90);
|
|
||||||
add_track->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_BEGIN,45);
|
|
||||||
left_pane->add_child(add_track);
|
|
||||||
|
|
||||||
remove_track = memnew( Button );
|
|
||||||
remove_track->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,85);
|
|
||||||
remove_track->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,25);
|
|
||||||
remove_track->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,60);
|
|
||||||
remove_track->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_BEGIN,45);
|
|
||||||
left_pane->add_child(remove_track);
|
|
||||||
|
|
||||||
move_up_track = memnew( Button );
|
|
||||||
move_up_track->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,55);
|
|
||||||
move_up_track->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,25);
|
|
||||||
move_up_track->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,30);
|
|
||||||
move_up_track->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_BEGIN,45);
|
|
||||||
left_pane->add_child(move_up_track);
|
|
||||||
|
|
||||||
move_down_track = memnew( Button );
|
|
||||||
move_down_track->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,25);
|
|
||||||
move_down_track->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,25);
|
|
||||||
move_down_track->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,0);
|
|
||||||
move_down_track->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_BEGIN,45);
|
|
||||||
left_pane->add_child(move_down_track);
|
|
||||||
|
|
||||||
tracks = memnew(Tree);
|
|
||||||
tracks->set_columns(2);
|
|
||||||
tracks->set_column_expand(0,false);
|
|
||||||
tracks->set_column_min_width(0,55);
|
|
||||||
tracks->set_column_expand(1,true);
|
|
||||||
tracks->set_column_min_width(1,100);
|
|
||||||
tracks->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,55);
|
|
||||||
tracks->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,0);
|
|
||||||
tracks->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,10);
|
|
||||||
tracks->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,5);
|
|
||||||
tracks->set_hide_root(true);
|
|
||||||
left_pane->add_child(tracks);
|
|
||||||
|
|
||||||
|
|
||||||
Control *right_pane = memnew( Control );
|
|
||||||
panel->add_child(right_pane);
|
|
||||||
right_pane->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_RATIO,0.5);
|
|
||||||
right_pane->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,5);
|
|
||||||
right_pane->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,0);
|
|
||||||
|
|
||||||
l = memnew( Label );
|
|
||||||
l->set_text("Track Keys:");
|
|
||||||
l->set_pos(Point2(5,5));
|
|
||||||
right_pane->add_child(l);
|
|
||||||
|
|
||||||
time_icon = memnew( TextureFrame );
|
|
||||||
time_icon->set_pos(Point2(8,28));
|
|
||||||
right_pane->add_child(time_icon);
|
|
||||||
|
|
||||||
key_time = memnew( LineEdit );
|
|
||||||
key_time->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,24);
|
|
||||||
key_time->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,160);
|
|
||||||
key_time->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,25);
|
|
||||||
key_time->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_BEGIN,45);
|
|
||||||
key_time->set_text("0.0");
|
|
||||||
right_pane->add_child(key_time);
|
|
||||||
|
|
||||||
key_type = memnew( OptionButton );
|
|
||||||
key_type->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,160);
|
|
||||||
key_type->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,60);
|
|
||||||
key_type->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,25);
|
|
||||||
key_type->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_BEGIN,45);
|
|
||||||
right_pane->add_child(key_type);
|
|
||||||
|
|
||||||
for(int i=0;i<Variant::VARIANT_MAX;i++) {
|
|
||||||
|
|
||||||
key_type->add_item(Variant::get_type_name(Variant::Type(i)));
|
|
||||||
}
|
|
||||||
|
|
||||||
add_key = memnew( Button );
|
|
||||||
add_key->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,55);
|
|
||||||
add_key->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,30);
|
|
||||||
add_key->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,25);
|
|
||||||
add_key->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_BEGIN,45);
|
|
||||||
right_pane->add_child(add_key);
|
|
||||||
|
|
||||||
remove_key = memnew( Button );
|
|
||||||
remove_key->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,25);
|
|
||||||
remove_key->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,0);
|
|
||||||
remove_key->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,25);
|
|
||||||
remove_key->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_BEGIN,45);
|
|
||||||
right_pane->add_child(remove_key);
|
|
||||||
|
|
||||||
key_editor = memnew(PropertyEditor);
|
|
||||||
key_editor->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,55);
|
|
||||||
key_editor->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,0);
|
|
||||||
key_editor->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,10);
|
|
||||||
key_editor->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,5);
|
|
||||||
key_editor->hide_top_label();
|
|
||||||
|
|
||||||
right_pane->add_child(key_editor);
|
|
||||||
|
|
||||||
track_editor = memnew( AnimationEditor_TrackEditor );
|
|
||||||
track_editor->anim_editor=this;
|
|
||||||
selected_track=-1;
|
|
||||||
|
|
||||||
add_track->connect("pressed", this,"_track_added");
|
|
||||||
remove_track->connect("pressed", this,"_track_removed");
|
|
||||||
move_up_track->connect("pressed", this,"_track_moved_up");
|
|
||||||
move_down_track->connect("pressed", this,"_track_moved_down");
|
|
||||||
tracks->connect("cell_selected", this,"_track_selected");
|
|
||||||
tracks->connect("item_edited", this,"_track_path_changed");
|
|
||||||
add_key->connect("pressed", this,"_key_added");
|
|
||||||
remove_key->connect("pressed", this,"_key_removed");
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimationEditor::~AnimationEditor() {
|
|
||||||
|
|
||||||
memdelete(track_editor);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimationEditorPlugin::edit(Object *p_node) {
|
|
||||||
|
|
||||||
animation_editor->set_undo_redo(&get_undo_redo());
|
|
||||||
if (p_node && p_node->cast_to<Animation>()) {
|
|
||||||
animation_editor->edit( p_node->cast_to<Animation>() );
|
|
||||||
animation_editor->show();
|
|
||||||
} else
|
|
||||||
animation_editor->hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AnimationEditorPlugin::handles(Object *p_node) const{
|
|
||||||
|
|
||||||
return p_node->is_type("Animation");
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnimationEditorPlugin::make_visible(bool p_visible){
|
|
||||||
|
|
||||||
if (p_visible)
|
|
||||||
animation_editor->show();
|
|
||||||
else
|
|
||||||
animation_editor->hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimationEditorPlugin::AnimationEditorPlugin(EditorNode *p_node) {
|
|
||||||
|
|
||||||
animation_editor = memnew( AnimationEditor );
|
|
||||||
|
|
||||||
p_node->get_viewport()->add_child(animation_editor);
|
|
||||||
animation_editor->set_area_as_parent_rect();
|
|
||||||
animation_editor->hide();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,123 +0,0 @@
|
||||||
/*************************************************************************/
|
|
||||||
/* animation_editor_plugin.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 ANIMATION_EDITOR_PLUGIN_H
|
|
||||||
#define ANIMATION_EDITOR_PLUGIN_H
|
|
||||||
|
|
||||||
#include "scene/resources/animation.h"
|
|
||||||
#include "scene/gui/texture_frame.h"
|
|
||||||
#include "scene/gui/option_button.h"
|
|
||||||
#include "tools/editor/editor_node.h"
|
|
||||||
#include "tools/editor/property_editor.h"
|
|
||||||
#include "undo_redo.h"
|
|
||||||
class AnimationEditor_TrackEditor;
|
|
||||||
|
|
||||||
class AnimationEditor : public Control {
|
|
||||||
|
|
||||||
OBJ_TYPE( AnimationEditor, Control );
|
|
||||||
|
|
||||||
Panel *panel;
|
|
||||||
Ref<Animation> animation;
|
|
||||||
|
|
||||||
Button *add_track;
|
|
||||||
Button *remove_track;
|
|
||||||
Button *move_up_track;
|
|
||||||
Button *move_down_track;
|
|
||||||
|
|
||||||
Button *add_key;
|
|
||||||
Button *remove_key;
|
|
||||||
|
|
||||||
LineEdit *key_time;
|
|
||||||
OptionButton *track_type;
|
|
||||||
OptionButton *key_type;
|
|
||||||
TextureFrame *time_icon;
|
|
||||||
|
|
||||||
Tree *tracks;
|
|
||||||
PropertyEditor *key_editor;
|
|
||||||
AnimationEditor_TrackEditor *track_editor;
|
|
||||||
int selected_track;
|
|
||||||
|
|
||||||
void _track_selected();
|
|
||||||
void _track_added();
|
|
||||||
void _track_removed();
|
|
||||||
void _track_moved_up();
|
|
||||||
void _track_moved_down();
|
|
||||||
void _track_path_changed();
|
|
||||||
|
|
||||||
void _key_added();
|
|
||||||
void _key_removed();
|
|
||||||
|
|
||||||
|
|
||||||
void _update_track_keys();
|
|
||||||
void update_anim();
|
|
||||||
|
|
||||||
UndoRedo *undo_redo;
|
|
||||||
|
|
||||||
void _internal_set_selected_track(int p_which,const Ref<Animation>& p_anim);
|
|
||||||
void _internal_check_update(Ref<Animation> p_anim);
|
|
||||||
|
|
||||||
friend class AnimationEditor_TrackEditor;
|
|
||||||
void _internal_set_key(int p_track, float p_time, float p_transition,const Variant& p_value);
|
|
||||||
void _internal_set_interpolation_type(int p_track,Animation::InterpolationType p_type);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void _notification(int p_what);
|
|
||||||
static void _bind_methods();
|
|
||||||
public:
|
|
||||||
|
|
||||||
void set_undo_redo(UndoRedo *p_undo_redo) { undo_redo=p_undo_redo; }
|
|
||||||
void edit(const Ref<Animation>& p_animation);
|
|
||||||
|
|
||||||
AnimationEditor();
|
|
||||||
~AnimationEditor();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class AnimationEditorPlugin : public EditorPlugin {
|
|
||||||
|
|
||||||
OBJ_TYPE( AnimationEditorPlugin, EditorPlugin );
|
|
||||||
|
|
||||||
AnimationEditor *animation_editor;
|
|
||||||
EditorNode *editor;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
|
|
||||||
virtual String get_name() const { return "Animation"; }
|
|
||||||
bool has_main_screen() const { return false; }
|
|
||||||
virtual void edit(Object *p_node);
|
|
||||||
virtual bool handles(Object *p_node) const;
|
|
||||||
virtual void make_visible(bool p_visible);
|
|
||||||
|
|
||||||
AnimationEditorPlugin(EditorNode *p_node);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,905 +0,0 @@
|
||||||
/*************************************************************************/
|
|
||||||
/* font_editor_plugin.cpp */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* 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. */
|
|
||||||
/*************************************************************************/
|
|
||||||
#include "font_editor_plugin.h"
|
|
||||||
#include "os/file_access.h"
|
|
||||||
#ifdef FREETYPE_ENABLED
|
|
||||||
|
|
||||||
#include <ft2build.h>
|
|
||||||
#include FT_FREETYPE_H
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "core/io/resource_saver.h"
|
|
||||||
|
|
||||||
void FontEditor::edit(const Ref<Font>& p_font) {
|
|
||||||
|
|
||||||
font=p_font;
|
|
||||||
label->add_font_override("font",font);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FontEditor::_preview_text_changed(const String& p_text) {
|
|
||||||
|
|
||||||
label->set_text(p_text);
|
|
||||||
}
|
|
||||||
struct FontData {
|
|
||||||
|
|
||||||
Vector<uint8_t> bitmap;
|
|
||||||
int width,height;
|
|
||||||
int ofs_x; //ofset to center, from ABOVE
|
|
||||||
int ofs_y; //ofset to begining, from LEFT
|
|
||||||
int valign; //vertical alignment
|
|
||||||
int halign;
|
|
||||||
int advance;
|
|
||||||
int character;
|
|
||||||
int glyph;
|
|
||||||
|
|
||||||
int texture;
|
|
||||||
// bool printable;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct FontDataSort {
|
|
||||||
|
|
||||||
bool operator()(const FontData *p_A,const FontData *p_B) const {
|
|
||||||
return p_A->height > p_B->height;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct KerningKey {
|
|
||||||
|
|
||||||
CharType A,B;
|
|
||||||
bool operator<(const KerningKey& p_k) const { return (A==p_k.A)?(B<p_k.B):(A<p_k.A); }
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
void FontEditor::_export_fnt(const String& p_name, Ref<Font> p_font) {
|
|
||||||
|
|
||||||
String fnt_name = p_name + ".fnt";
|
|
||||||
FileAccess* f = FileAccess::open(fnt_name, FileAccess::WRITE);
|
|
||||||
ERR_FAIL_COND(!f);
|
|
||||||
|
|
||||||
f->store_string(String("info face=\"") + p_font->get_name() + "\" size=" + String::num_real(font->get_height()) + " bold=0 italic=0 charset=\"\" unicode=0 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=4,4\n");
|
|
||||||
|
|
||||||
Vector2 size = p_font->get_texture(0)->get_size();
|
|
||||||
f->store_string(String("common lineHeight=") + String::num(font->get_height()) + " base=" + String::num(font->get_ascent()) + " scaleW=" + String::num(size.x) + " scaleH=" + String::num(size.y) + " pages="+String::num(p_font->get_texture_count()) + " packed=0\n");
|
|
||||||
|
|
||||||
for (int i=0; i<p_font->get_texture_count(); i++) {
|
|
||||||
|
|
||||||
f->store_string(String("page id=")+String::num(i)+ " file=\""+ p_name.get_file() + "_" +String::num(i)+".png\"\n");
|
|
||||||
};
|
|
||||||
|
|
||||||
f->store_string(String("chars count=")+String::num(p_font->get_character_count()) + "\n");
|
|
||||||
|
|
||||||
Vector<CharType> keys = p_font->get_char_keys();
|
|
||||||
keys.sort();
|
|
||||||
for (int i=0; i<keys.size(); i++) {
|
|
||||||
|
|
||||||
Font::Character c = p_font->get_character(keys[i]);
|
|
||||||
int width = c.rect.size.x;
|
|
||||||
if (keys[i] == 32) {
|
|
||||||
width = c.advance;
|
|
||||||
};
|
|
||||||
f->store_string(String("char id=") + String::num(keys[i]) + " x=" + String::num(c.rect.pos.x) + " y=" + String::num(c.rect.pos.y) +
|
|
||||||
" width=" + String::num(width) + " height=" + String::num(c.rect.size.y) +
|
|
||||||
" xoffset=" + String::num(c.h_align) + " yoffset=" + String::num(c.v_align) +
|
|
||||||
" xadvance=" + String::num(c.advance) + " page=" + String::num(c.texture_idx) +
|
|
||||||
" chnl=0 letter=\"\"\n");
|
|
||||||
};
|
|
||||||
|
|
||||||
f->close();
|
|
||||||
|
|
||||||
for (int i=0; i<p_font->get_texture_count(); i++) {
|
|
||||||
|
|
||||||
ResourceSaver::save(p_name + "_" + String::num(i) + ".png", p_font->get_texture(i));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
void FontEditor::_import_fnt(const String& p_string) {
|
|
||||||
//fnt format used by angelcode bmfont
|
|
||||||
//http://www.angelcode.com/products/bmfont/
|
|
||||||
|
|
||||||
FileAccess *f = FileAccess::open(p_string,FileAccess::READ);
|
|
||||||
|
|
||||||
if (!f) {
|
|
||||||
|
|
||||||
ERR_EXPLAIN("Can't open font: "+p_string);
|
|
||||||
ERR_FAIL();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
font->clear();
|
|
||||||
|
|
||||||
while(true) {
|
|
||||||
|
|
||||||
String line=f->get_line();
|
|
||||||
|
|
||||||
int delimiter=line.find(" ");
|
|
||||||
String type=line.substr(0,delimiter);
|
|
||||||
int pos = delimiter+1;
|
|
||||||
Map<String,String> keys;
|
|
||||||
|
|
||||||
while (pos < line.size() && line[pos]==' ')
|
|
||||||
pos++;
|
|
||||||
|
|
||||||
|
|
||||||
while(pos<line.size()) {
|
|
||||||
|
|
||||||
int eq = line.find("=",pos);
|
|
||||||
if (eq==-1)
|
|
||||||
break;
|
|
||||||
String key=line.substr(pos,eq-pos);
|
|
||||||
int end=-1;
|
|
||||||
String value;
|
|
||||||
if (line[eq+1]=='"') {
|
|
||||||
end=line.find("\"",eq+2);
|
|
||||||
if (end==-1)
|
|
||||||
break;
|
|
||||||
value=line.substr(eq+2,end-1-eq-1);
|
|
||||||
pos=end+1;
|
|
||||||
} else {
|
|
||||||
end=line.find(" ",eq+1);
|
|
||||||
if (end==-1)
|
|
||||||
end=line.size();
|
|
||||||
|
|
||||||
value=line.substr(eq+1,end-eq);
|
|
||||||
|
|
||||||
pos=end;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
while (pos<line.size() && line[pos]==' ')
|
|
||||||
pos++;
|
|
||||||
|
|
||||||
|
|
||||||
keys[key]=value;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (type=="info") {
|
|
||||||
|
|
||||||
if (keys.has("face"))
|
|
||||||
font->set_name(keys["face"]);
|
|
||||||
//if (keys.has("size"))
|
|
||||||
// font->set_height(keys["size"].to_int());
|
|
||||||
|
|
||||||
} else if (type=="common") {
|
|
||||||
|
|
||||||
if (keys.has("lineHeight"))
|
|
||||||
font->set_height(keys["lineHeight"].to_int());
|
|
||||||
if (keys.has("base"))
|
|
||||||
font->set_ascent(keys["base"].to_int());
|
|
||||||
|
|
||||||
} else if (type=="page") {
|
|
||||||
|
|
||||||
if (keys.has("file")) {
|
|
||||||
|
|
||||||
String file = keys["file"];
|
|
||||||
file=p_string.get_base_dir()+"/"+file;
|
|
||||||
Ref<Texture> tex = ResourceLoader::load(file);
|
|
||||||
if (tex.is_null()) {
|
|
||||||
ERR_PRINT("Can't load font texture!");
|
|
||||||
} else {
|
|
||||||
font->add_texture(tex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (type=="char") {
|
|
||||||
|
|
||||||
CharType idx=0;
|
|
||||||
if (keys.has("id"))
|
|
||||||
idx=keys["id"].to_int();
|
|
||||||
|
|
||||||
Rect2 rect;
|
|
||||||
|
|
||||||
if (keys.has("x"))
|
|
||||||
rect.pos.x=keys["x"].to_int();
|
|
||||||
if (keys.has("y"))
|
|
||||||
rect.pos.y=keys["y"].to_int();
|
|
||||||
if (keys.has("width"))
|
|
||||||
rect.size.width=keys["width"].to_int();
|
|
||||||
if (keys.has("height"))
|
|
||||||
rect.size.height=keys["height"].to_int();
|
|
||||||
|
|
||||||
Point2 ofs;
|
|
||||||
|
|
||||||
if (keys.has("xoffset"))
|
|
||||||
ofs.x=keys["xoffset"].to_int();
|
|
||||||
if (keys.has("yoffset"))
|
|
||||||
ofs.y=keys["yoffset"].to_int();
|
|
||||||
|
|
||||||
int texture=0;
|
|
||||||
if (keys.has("page"))
|
|
||||||
texture=keys["page"].to_int();
|
|
||||||
int advance=-1;
|
|
||||||
if (keys.has("xadvance"))
|
|
||||||
advance=keys["xadvance"].to_int();
|
|
||||||
|
|
||||||
font->add_char(idx,texture,rect,ofs,advance);
|
|
||||||
|
|
||||||
} else if (type=="kerning") {
|
|
||||||
|
|
||||||
CharType first=0,second=0;
|
|
||||||
int k=0;
|
|
||||||
|
|
||||||
if (keys.has("first"))
|
|
||||||
first=keys["first"].to_int();
|
|
||||||
if (keys.has("second"))
|
|
||||||
second=keys["second"].to_int();
|
|
||||||
if (keys.has("amount"))
|
|
||||||
k=keys["amount"].to_int();
|
|
||||||
|
|
||||||
font->add_kerning_pair(first,second,-k);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (f->eof_reached())
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
memdelete(f);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void FontEditor::_import_ttf(const String& p_string) {
|
|
||||||
|
|
||||||
#ifdef FREETYPE_ENABLED
|
|
||||||
FT_Library library; /* handle to library */
|
|
||||||
FT_Face face; /* handle to face object */
|
|
||||||
|
|
||||||
Vector<FontData*> font_data_list;
|
|
||||||
|
|
||||||
int error = FT_Init_FreeType( &library );
|
|
||||||
|
|
||||||
ERR_EXPLAIN("Error initializing FreeType.");
|
|
||||||
ERR_FAIL_COND( error !=0 );
|
|
||||||
|
|
||||||
|
|
||||||
error = FT_New_Face( library, p_string.utf8().get_data(),0,&face );
|
|
||||||
|
|
||||||
if ( error == FT_Err_Unknown_File_Format ) {
|
|
||||||
ERR_EXPLAIN("Unknown font format.");
|
|
||||||
FT_Done_FreeType( library );
|
|
||||||
} else if ( error ) {
|
|
||||||
|
|
||||||
ERR_EXPLAIN("Error loading font.");
|
|
||||||
FT_Done_FreeType( library );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ERR_FAIL_COND(error);
|
|
||||||
|
|
||||||
|
|
||||||
int height=0;
|
|
||||||
int ascent=0;
|
|
||||||
int font_spacing=0;
|
|
||||||
|
|
||||||
int size=font_size->get_text().to_int();
|
|
||||||
|
|
||||||
error = FT_Set_Char_Size(face,0,64*size,512,512);
|
|
||||||
|
|
||||||
if ( error ) {
|
|
||||||
FT_Done_FreeType( library );
|
|
||||||
ERR_EXPLAIN("Invalid font size. ");
|
|
||||||
ERR_FAIL_COND( error );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
error = FT_Set_Pixel_Sizes(face,0,size);
|
|
||||||
|
|
||||||
FT_GlyphSlot slot = face->glyph;
|
|
||||||
|
|
||||||
// error = FT_Set_Charmap(face,ft_encoding_unicode ); /* encoding.. */
|
|
||||||
|
|
||||||
|
|
||||||
/* PRINT CHARACTERS TO INDIVIDUAL BITMAPS */
|
|
||||||
|
|
||||||
|
|
||||||
// int space_size=5; //size for space, if none found.. 5!
|
|
||||||
// int min_valign=500; //some ridiculous number
|
|
||||||
|
|
||||||
FT_ULong charcode;
|
|
||||||
FT_UInt gindex;
|
|
||||||
|
|
||||||
int max_up=-1324345; ///gibberish
|
|
||||||
int max_down=124232;
|
|
||||||
|
|
||||||
Map<KerningKey,int> kerning_map;
|
|
||||||
|
|
||||||
charcode = FT_Get_First_Char( face, &gindex );
|
|
||||||
|
|
||||||
int xsize=0;
|
|
||||||
while ( gindex != 0 )
|
|
||||||
{
|
|
||||||
|
|
||||||
bool skip=false;
|
|
||||||
error = FT_Load_Char( face, charcode, FT_LOAD_RENDER );
|
|
||||||
if (error) skip=true;
|
|
||||||
else error = FT_Render_Glyph( face->glyph, ft_render_mode_normal );
|
|
||||||
if (error) skip=true;
|
|
||||||
|
|
||||||
|
|
||||||
if (!skip && (import_chars.has(charcode) && import_chars[charcode] != 0)) {
|
|
||||||
|
|
||||||
skip = false;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (import_option->get_selected() == 0 && charcode>127)
|
|
||||||
skip=true;
|
|
||||||
if (import_option->get_selected() == 1 && charcode>0xFE)
|
|
||||||
skip=true;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (charcode<=32) //
|
|
||||||
skip=true;
|
|
||||||
|
|
||||||
if (skip) {
|
|
||||||
charcode=FT_Get_Next_Char(face,charcode,&gindex);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
FontData * fdata = memnew( FontData );
|
|
||||||
fdata->bitmap.resize( slot->bitmap.width*slot->bitmap.rows );
|
|
||||||
fdata->width=slot->bitmap.width;
|
|
||||||
fdata->height=slot->bitmap.rows;
|
|
||||||
fdata->character=charcode;
|
|
||||||
fdata->glyph=FT_Get_Char_Index(face,charcode);
|
|
||||||
if (charcode=='x')
|
|
||||||
xsize=slot->bitmap.width;
|
|
||||||
|
|
||||||
|
|
||||||
if (charcode<127) {
|
|
||||||
if (slot->bitmap_top>max_up) {
|
|
||||||
|
|
||||||
max_up=slot->bitmap_top;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if ( (slot->bitmap_top - fdata->height)<max_down ) {
|
|
||||||
|
|
||||||
max_down=slot->bitmap_top - fdata->height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fdata->valign=slot->bitmap_top;
|
|
||||||
fdata->halign=slot->bitmap_left;
|
|
||||||
fdata->advance=(slot->advance.x+(1<<5))>>6;
|
|
||||||
fdata->advance+=font_spacing;
|
|
||||||
|
|
||||||
for (int i=0;i<slot->bitmap.width;i++) {
|
|
||||||
for (int j=0;j<slot->bitmap.rows;j++) {
|
|
||||||
|
|
||||||
fdata->bitmap[j*slot->bitmap.width+i]=slot->bitmap.buffer[j*slot->bitmap.width+i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
font_data_list.push_back(fdata);
|
|
||||||
charcode=FT_Get_Next_Char(face,charcode,&gindex);
|
|
||||||
// printf("reading char %i\n",charcode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SPACE */
|
|
||||||
|
|
||||||
FontData *spd = memnew( FontData );
|
|
||||||
spd->advance=0;
|
|
||||||
spd->character=' ';
|
|
||||||
spd->halign=0;
|
|
||||||
spd->valign=0;
|
|
||||||
spd->width=0;
|
|
||||||
spd->height=0;
|
|
||||||
spd->ofs_x=0;
|
|
||||||
spd->ofs_y=0;
|
|
||||||
|
|
||||||
if (!FT_Load_Char( face, ' ', FT_LOAD_RENDER ) && !FT_Render_Glyph( face->glyph, ft_render_mode_normal )) {
|
|
||||||
|
|
||||||
spd->advance = slot->advance.x>>6;
|
|
||||||
spd->advance+=font_spacing;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
spd->advance=xsize;
|
|
||||||
spd->advance+=font_spacing;
|
|
||||||
}
|
|
||||||
|
|
||||||
font_data_list.push_back(spd);
|
|
||||||
|
|
||||||
Map<CharType, bool> exported;
|
|
||||||
for (int i=0; i<font_data_list.size(); i++) {
|
|
||||||
exported[font_data_list[i]->character] = true;
|
|
||||||
};
|
|
||||||
int missing = 0;
|
|
||||||
for(Map<CharType,int>::Element *E=import_chars.front();E;E=E->next()) {
|
|
||||||
CharType c = E->key();
|
|
||||||
if (!exported.has(c)) {
|
|
||||||
CharType str[2] = {c, 0};
|
|
||||||
printf("** Warning: character %i (%ls) not exported\n", (int)c, str);
|
|
||||||
++missing;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
printf("total %i/%i\n", missing, import_chars.size());
|
|
||||||
|
|
||||||
/* KERNING */
|
|
||||||
|
|
||||||
|
|
||||||
for(int i=0;i<font_data_list.size();i++) {
|
|
||||||
|
|
||||||
for(int j=0;j<font_data_list.size();j++) {
|
|
||||||
|
|
||||||
FT_Vector delta;
|
|
||||||
FT_Get_Kerning( face, font_data_list[i]->glyph,font_data_list[j]->glyph, FT_KERNING_DEFAULT, &delta );
|
|
||||||
|
|
||||||
if (delta.x!=0) {
|
|
||||||
|
|
||||||
KerningKey kpk;
|
|
||||||
kpk.A = font_data_list[i]->character;
|
|
||||||
kpk.B = font_data_list[j]->character;
|
|
||||||
int kern = ((-delta.x)+(1<<5))>>6;
|
|
||||||
|
|
||||||
if (kern==0)
|
|
||||||
continue;
|
|
||||||
kerning_map[kpk]=kern;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
height=max_up-max_down;
|
|
||||||
ascent=max_up;
|
|
||||||
|
|
||||||
/* FIND OUT WHAT THE FONT HEIGHT FOR THIS IS */
|
|
||||||
|
|
||||||
/* ADJUST THE VALIGN FOR EACH CHARACTER */
|
|
||||||
|
|
||||||
for (int i=0;i<(int)font_data_list.size();i++) {
|
|
||||||
|
|
||||||
font_data_list[i]->valign=max_up-font_data_list[i]->valign;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ADD THE SPACEBAR CHARACTER */
|
|
||||||
/*
|
|
||||||
FontData * fdata = new FontData;
|
|
||||||
|
|
||||||
fdata->character=32;
|
|
||||||
fdata->bitmap=0;
|
|
||||||
fdata->width=xsize;
|
|
||||||
fdata->height=1;
|
|
||||||
fdata->valign=0;
|
|
||||||
|
|
||||||
font_data_list.push_back(fdata);
|
|
||||||
*/
|
|
||||||
/* SORT BY HEIGHT, SO THEY FIT BETTER ON THE TEXTURE */
|
|
||||||
|
|
||||||
font_data_list.sort_custom<FontDataSort>();
|
|
||||||
|
|
||||||
int spacing=2;
|
|
||||||
|
|
||||||
|
|
||||||
int use_width=256;
|
|
||||||
int use_max_height=256;
|
|
||||||
// int surf_idx=-1;
|
|
||||||
|
|
||||||
List<Size2> tex_sizes;
|
|
||||||
// int current_texture=0;
|
|
||||||
|
|
||||||
Size2 first(use_width,nearest_power_of_2( font_data_list[0]->height + spacing ));
|
|
||||||
Size2 *curtex=&tex_sizes.push_back(first)->get();
|
|
||||||
|
|
||||||
Point2 tex_ofs;
|
|
||||||
|
|
||||||
/* FIT (NOT COPY YEY) FACES IN TEXTURES */
|
|
||||||
|
|
||||||
int current_height=font_data_list[0]->height + spacing;
|
|
||||||
|
|
||||||
int font_margin=2;
|
|
||||||
|
|
||||||
|
|
||||||
for(int i=0;i<font_data_list.size();i++) {
|
|
||||||
|
|
||||||
FontData *fd=font_data_list[i];
|
|
||||||
|
|
||||||
if (tex_ofs.x+fd->width >= use_width) {
|
|
||||||
//end of column, advance a row
|
|
||||||
tex_ofs.x=0;
|
|
||||||
tex_ofs.y+=current_height+font_margin;
|
|
||||||
current_height=fd->height + spacing;
|
|
||||||
|
|
||||||
int new_tex_h = curtex->height;
|
|
||||||
|
|
||||||
while( tex_ofs.y+current_height > new_tex_h ) {
|
|
||||||
|
|
||||||
if (curtex->height * 2 > use_max_height) {
|
|
||||||
//oops, can't use this texture anymore..
|
|
||||||
Size2 newtex( use_width, nearest_power_of_2( fd->height + spacing ));
|
|
||||||
new_tex_h=newtex.height;
|
|
||||||
curtex=&tex_sizes.push_back(newtex)->get();
|
|
||||||
tex_ofs=Point2(0,0);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
new_tex_h*=2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
curtex->height=new_tex_h;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fd->ofs_x=tex_ofs.x;
|
|
||||||
fd->ofs_y=tex_ofs.y;
|
|
||||||
fd->texture=tex_sizes.size()-1;
|
|
||||||
|
|
||||||
tex_ofs.x+=fd->width+font_margin;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* WRITE FACES IN TEXTURES */
|
|
||||||
|
|
||||||
// create textures
|
|
||||||
|
|
||||||
Vector<DVector<uint8_t> >image_data;
|
|
||||||
Vector<int> image_widths;
|
|
||||||
Vector<DVector<uint8_t>::Write> image_ptrs;
|
|
||||||
image_ptrs.resize(tex_sizes.size());
|
|
||||||
|
|
||||||
for(int i=0;i<tex_sizes.size();i++) {
|
|
||||||
|
|
||||||
DVector<uint8_t> pixels;
|
|
||||||
int texsize=tex_sizes[i].width * tex_sizes[i].height * 2;
|
|
||||||
pixels.resize(texsize );
|
|
||||||
|
|
||||||
image_data.push_back(pixels);
|
|
||||||
image_widths.push_back( tex_sizes[i].width );
|
|
||||||
image_ptrs[i] = image_data[i].write();
|
|
||||||
for(int j=0;j<texsize;j++) {
|
|
||||||
|
|
||||||
image_ptrs[i][j]=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//blit textures with fonts
|
|
||||||
for(int i=0;i<font_data_list.size();i++) {
|
|
||||||
|
|
||||||
FontData *fd=font_data_list[i];
|
|
||||||
|
|
||||||
uint8_t *pixels = image_ptrs[fd->texture].ptr();
|
|
||||||
int width = image_widths[fd->texture];
|
|
||||||
|
|
||||||
for(int y=0;y<fd->height;y++) {
|
|
||||||
|
|
||||||
const uint8_t *src = &fd->bitmap[y*fd->width];
|
|
||||||
uint8_t *dst = &pixels[((fd->ofs_y+y)*width+fd->ofs_x)*2];
|
|
||||||
|
|
||||||
|
|
||||||
for(int x=0;x<fd->width;x++) {
|
|
||||||
|
|
||||||
dst[x<<1]=255; //white always
|
|
||||||
dst[(x<<1) +1]=src[x];
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//unlock writing
|
|
||||||
for(int i=0;i<image_ptrs.size();i++)
|
|
||||||
image_ptrs[i]=DVector<uint8_t>::Write();
|
|
||||||
|
|
||||||
/* CREATE FONT */
|
|
||||||
|
|
||||||
font->clear();
|
|
||||||
font->set_height(height);
|
|
||||||
font->set_ascent(ascent);
|
|
||||||
|
|
||||||
//register texures
|
|
||||||
for(int i=0;i<tex_sizes.size();i++) {
|
|
||||||
Image img(tex_sizes[i].width,tex_sizes[i].height,0,Image::FORMAT_GRAYSCALE_ALPHA,image_data[i]);
|
|
||||||
Ref<ImageTexture> tex = memnew( ImageTexture );
|
|
||||||
tex->create_from_image(img,0); //no filter, no repeat
|
|
||||||
font->add_texture(tex);
|
|
||||||
//tframe->set_texture(tex);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//register characters
|
|
||||||
|
|
||||||
for(int i=0;i<font_data_list.size();i++) {
|
|
||||||
FontData *fd=font_data_list[i];
|
|
||||||
|
|
||||||
font->add_char(fd->character,fd->texture,Rect2( fd->ofs_x, fd->ofs_y, fd->width, fd->height),Point2(fd->halign,fd->valign), fd->advance);
|
|
||||||
memdelete(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(Map<KerningKey,int>::Element *E=kerning_map.front();E;E=E->next()) {
|
|
||||||
|
|
||||||
font->add_kerning_pair(E->key().A,E->key().B,E->get());
|
|
||||||
}
|
|
||||||
|
|
||||||
FT_Done_FreeType( library );
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void FontEditor::_add_source() {
|
|
||||||
|
|
||||||
_source_file->popup_centered_ratio();
|
|
||||||
};
|
|
||||||
|
|
||||||
void FontEditor::_add_source_accept(const String& p_file) {
|
|
||||||
|
|
||||||
FileAccess* f = FileAccess::open(p_file, FileAccess::READ);
|
|
||||||
ERR_FAIL_COND(!f);
|
|
||||||
|
|
||||||
String line;
|
|
||||||
while ( !f->eof_reached() ) {
|
|
||||||
|
|
||||||
line = f->get_line();
|
|
||||||
for (int i=0; i<line.length(); i++) {
|
|
||||||
|
|
||||||
if (import_chars.has(line[i])) {
|
|
||||||
import_chars[line[i]] = import_chars[line[i]] + 1;
|
|
||||||
} else {
|
|
||||||
import_chars[line[i]] = 1;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
void FontEditor::_export_fnt_pressed() {
|
|
||||||
|
|
||||||
_export_file->popup_centered_ratio();
|
|
||||||
};
|
|
||||||
|
|
||||||
void FontEditor::_export_fnt_accept(const String& p_file) {
|
|
||||||
|
|
||||||
String name = p_file.replace(".fnt", "");
|
|
||||||
_export_fnt(name, font);
|
|
||||||
};
|
|
||||||
|
|
||||||
void FontEditor::_import_accept(const String& p_string) {
|
|
||||||
|
|
||||||
#ifdef FREETYPE_ENABLED
|
|
||||||
|
|
||||||
if (p_string.extension().nocasecmp_to("ttf")==0 || p_string.extension().nocasecmp_to("otf")==0) {
|
|
||||||
|
|
||||||
_import_ttf(p_string);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (p_string.extension().nocasecmp_to("fnt")==0) {
|
|
||||||
|
|
||||||
_import_fnt(p_string);
|
|
||||||
}
|
|
||||||
|
|
||||||
label->add_font_override("font",font);
|
|
||||||
label->notification(Control::NOTIFICATION_THEME_CHANGED);
|
|
||||||
label->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FontEditor::_import() {
|
|
||||||
|
|
||||||
|
|
||||||
file->popup_centered_ratio();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FontEditor::_bind_methods() {
|
|
||||||
|
|
||||||
ObjectTypeDB::bind_method("_import",&FontEditor::_import);
|
|
||||||
ObjectTypeDB::bind_method("_import_accept",&FontEditor::_import_accept);
|
|
||||||
ObjectTypeDB::bind_method("_preview_text_changed",&FontEditor::_preview_text_changed);
|
|
||||||
ObjectTypeDB::bind_method("_add_source",&FontEditor::_add_source);
|
|
||||||
ObjectTypeDB::bind_method("_add_source_accept",&FontEditor::_add_source_accept);
|
|
||||||
ObjectTypeDB::bind_method("_export_fnt_pressed",&FontEditor::_export_fnt_pressed);
|
|
||||||
ObjectTypeDB::bind_method("_export_fnt_accept",&FontEditor::_export_fnt_accept);
|
|
||||||
}
|
|
||||||
|
|
||||||
FontEditor::FontEditor() {
|
|
||||||
|
|
||||||
panel = memnew( Panel );
|
|
||||||
add_child(panel);
|
|
||||||
panel->set_area_as_parent_rect();
|
|
||||||
|
|
||||||
/*
|
|
||||||
tframe = memnew( TextureFrame );
|
|
||||||
|
|
||||||
tframe->set_anchor( MARGIN_RIGHT, ANCHOR_END );
|
|
||||||
tframe->set_anchor( MARGIN_BOTTOM, ANCHOR_END );
|
|
||||||
|
|
||||||
tframe->set_begin( Point2(5, 40 ) );
|
|
||||||
tframe->set_end( Point2(5,55 ) );
|
|
||||||
|
|
||||||
panel->add_child(tframe);
|
|
||||||
*/
|
|
||||||
|
|
||||||
Label *l = memnew( Label );
|
|
||||||
l->set_pos( Point2(5,13 ) );
|
|
||||||
l->set_text("Import: ");
|
|
||||||
|
|
||||||
panel->add_child(l);
|
|
||||||
|
|
||||||
l = memnew( Label );
|
|
||||||
l->set_pos( Point2(25,37 ) );
|
|
||||||
l->set_text("Size: ");
|
|
||||||
|
|
||||||
panel->add_child(l);
|
|
||||||
|
|
||||||
font_size = memnew( LineEdit );
|
|
||||||
font_size->set_text("12");
|
|
||||||
font_size->set_pos( Point2(70,35 ) );
|
|
||||||
font_size->set_size( Size2(40,10 ) );
|
|
||||||
panel->add_child(font_size);
|
|
||||||
|
|
||||||
l = memnew( Label );
|
|
||||||
l->set_pos( Point2(140,37 ) );
|
|
||||||
l->set_text("Encoding: ");
|
|
||||||
|
|
||||||
panel->add_child(l);
|
|
||||||
|
|
||||||
import_option = memnew( OptionButton );
|
|
||||||
import_option->add_item("Ascii");
|
|
||||||
import_option->add_item("Latin");
|
|
||||||
import_option->add_item("Full Unicode");
|
|
||||||
import_option->select(1);
|
|
||||||
|
|
||||||
import_option->set_pos( Point2( 215,35 ) );
|
|
||||||
import_option->set_size( Point2( 100,12 ) );
|
|
||||||
|
|
||||||
panel->add_child(import_option);
|
|
||||||
|
|
||||||
Button* import = memnew( Button );
|
|
||||||
import->set_text("Import:..");
|
|
||||||
import->set_begin( Point2(80,35) );
|
|
||||||
import->set_end( Point2(10,45) );
|
|
||||||
|
|
||||||
import->set_anchor( MARGIN_LEFT, ANCHOR_END );
|
|
||||||
import->set_anchor( MARGIN_RIGHT, ANCHOR_END );
|
|
||||||
|
|
||||||
panel->add_child(import);
|
|
||||||
|
|
||||||
Button* add_source = memnew( Button );
|
|
||||||
add_source->set_text("Add Source...");
|
|
||||||
add_source->set_begin( Point2(180,35) );
|
|
||||||
add_source->set_end( Point2(90,45) );
|
|
||||||
add_source->set_anchor( MARGIN_LEFT, ANCHOR_END );
|
|
||||||
add_source->set_anchor( MARGIN_RIGHT, ANCHOR_END );
|
|
||||||
|
|
||||||
panel->add_child(add_source);
|
|
||||||
|
|
||||||
file = memnew( FileDialog );
|
|
||||||
file->set_access(FileDialog::ACCESS_FILESYSTEM);
|
|
||||||
|
|
||||||
_source_file = memnew( FileDialog );
|
|
||||||
_source_file->set_access(FileDialog::ACCESS_FILESYSTEM);
|
|
||||||
_source_file->set_mode(FileDialog::MODE_OPEN_FILE);
|
|
||||||
_source_file->connect("file_selected", this, "_add_source_accept");
|
|
||||||
panel->add_child( _source_file );
|
|
||||||
|
|
||||||
Button* export_fnt = memnew(Button);
|
|
||||||
export_fnt->set_text("Export fnt");
|
|
||||||
export_fnt->set_begin(Point2(80, 65));
|
|
||||||
export_fnt->set_end(Point2(10, 75));
|
|
||||||
export_fnt->set_anchor( MARGIN_LEFT, ANCHOR_END );
|
|
||||||
export_fnt->set_anchor( MARGIN_RIGHT, ANCHOR_END );
|
|
||||||
export_fnt->connect("pressed", this, "_export_fnt_pressed");
|
|
||||||
panel->add_child( export_fnt );
|
|
||||||
|
|
||||||
_export_file = memnew(FileDialog);
|
|
||||||
_export_file->set_access(FileDialog::ACCESS_FILESYSTEM);
|
|
||||||
_export_file->set_mode(FileDialog::MODE_SAVE_FILE);
|
|
||||||
_export_file->connect("file_selected", this, "_export_fnt_accept");
|
|
||||||
panel->add_child(_export_file);
|
|
||||||
|
|
||||||
l = memnew( Label );
|
|
||||||
l->set_pos( Point2(5,65 ) );
|
|
||||||
l->set_text("Preview Text: ");
|
|
||||||
|
|
||||||
panel->add_child(l);
|
|
||||||
|
|
||||||
preview_text = memnew( LineEdit );
|
|
||||||
preview_text->set_anchor( MARGIN_RIGHT, ANCHOR_END );
|
|
||||||
preview_text->set_begin( Point2(25,85 ) );
|
|
||||||
preview_text->set_end( Point2(10,95 ) );
|
|
||||||
panel->add_child(preview_text);
|
|
||||||
preview_text->connect("text_changed", this,"_preview_text_changed");
|
|
||||||
preview_text->set_text("The quick brown fox jumped over the lazy dog.");
|
|
||||||
|
|
||||||
l = memnew( Label );
|
|
||||||
l->set_pos( Point2(5,115 ) );
|
|
||||||
l->set_text("Preview: ");
|
|
||||||
|
|
||||||
panel->add_child(l);
|
|
||||||
|
|
||||||
label = memnew( Label );
|
|
||||||
label->set_autowrap(true);
|
|
||||||
|
|
||||||
label->set_anchor( MARGIN_RIGHT, ANCHOR_END );
|
|
||||||
label->set_anchor( MARGIN_BOTTOM, ANCHOR_END );
|
|
||||||
|
|
||||||
label->set_begin( Point2(5, 135 ) );
|
|
||||||
label->set_end( Point2(5,5 ) );
|
|
||||||
|
|
||||||
label->set_text("The quick brown fox jumped over the lazy dog.");
|
|
||||||
label->set_align( Label::ALIGN_CENTER );
|
|
||||||
|
|
||||||
panel->add_child(label);
|
|
||||||
|
|
||||||
#ifdef FREETYPE_ENABLED
|
|
||||||
|
|
||||||
file->add_filter("*.ttf");
|
|
||||||
file->add_filter("*.otf");
|
|
||||||
#endif
|
|
||||||
file->add_filter("*.fnt ; AngelCode BMFont");
|
|
||||||
|
|
||||||
file->set_mode(FileDialog::MODE_OPEN_FILE);
|
|
||||||
panel->add_child( file );
|
|
||||||
|
|
||||||
import->connect("pressed", this,"_import");
|
|
||||||
file->connect("file_selected", this,"_import_accept");
|
|
||||||
add_source->connect("pressed", this, "_add_source");
|
|
||||||
}
|
|
||||||
|
|
||||||
void FontEditorPlugin::edit(Object *p_node) {
|
|
||||||
|
|
||||||
if (p_node && p_node->cast_to<Font>()) {
|
|
||||||
font_editor->edit( p_node->cast_to<Font>() );
|
|
||||||
font_editor->show();
|
|
||||||
} else
|
|
||||||
font_editor->hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FontEditorPlugin::handles(Object *p_node) const{
|
|
||||||
|
|
||||||
return p_node->is_type("Font");
|
|
||||||
}
|
|
||||||
|
|
||||||
void FontEditorPlugin::make_visible(bool p_visible){
|
|
||||||
|
|
||||||
if (p_visible)
|
|
||||||
font_editor->show();
|
|
||||||
else
|
|
||||||
font_editor->hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
FontEditorPlugin::FontEditorPlugin(EditorNode *p_node) {
|
|
||||||
|
|
||||||
font_editor = memnew( FontEditor );
|
|
||||||
|
|
||||||
p_node->get_viewport()->add_child(font_editor);
|
|
||||||
font_editor->set_area_as_parent_rect();
|
|
||||||
font_editor->hide();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,100 +0,0 @@
|
||||||
/*************************************************************************/
|
|
||||||
/* font_editor_plugin.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 FONT_EDITOR_PLUGIN_H
|
|
||||||
#define FONT_EDITOR_PLUGIN_H
|
|
||||||
|
|
||||||
#include "scene/resources/font.h"
|
|
||||||
#include "scene/gui/texture_frame.h"
|
|
||||||
#include "scene/gui/option_button.h"
|
|
||||||
#include "tools/editor/editor_node.h"
|
|
||||||
|
|
||||||
|
|
||||||
class FontEditor : public Control {
|
|
||||||
|
|
||||||
OBJ_TYPE( FontEditor, Control );
|
|
||||||
|
|
||||||
Panel *panel;
|
|
||||||
LineEdit *font_size;
|
|
||||||
//TextureFrame *tframe; //for debug
|
|
||||||
Label *label;
|
|
||||||
LineEdit *preview_text;
|
|
||||||
FileDialog *file;
|
|
||||||
FileDialog* _source_file;
|
|
||||||
FileDialog* _export_file;
|
|
||||||
OptionButton *import_option;
|
|
||||||
|
|
||||||
Ref<Font> font;
|
|
||||||
|
|
||||||
Map<CharType, int> import_chars;
|
|
||||||
|
|
||||||
void _export_fnt(const String& p_name, Ref<Font> p_font);
|
|
||||||
void _export_fnt_pressed();
|
|
||||||
void _export_fnt_accept(const String& p_file);
|
|
||||||
|
|
||||||
void _import_ttf(const String& p_string);
|
|
||||||
void _import_fnt(const String& p_string);
|
|
||||||
void _preview_text_changed(const String& p_text);
|
|
||||||
|
|
||||||
void _add_source();
|
|
||||||
void _add_source_accept(const String& p_file);
|
|
||||||
|
|
||||||
void _import_accept(const String&);
|
|
||||||
void _import();
|
|
||||||
protected:
|
|
||||||
static void _bind_methods();
|
|
||||||
public:
|
|
||||||
|
|
||||||
void edit(const Ref<Font>& p_font);
|
|
||||||
|
|
||||||
FontEditor();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class FontEditorPlugin : public EditorPlugin {
|
|
||||||
|
|
||||||
OBJ_TYPE( FontEditorPlugin, EditorPlugin );
|
|
||||||
|
|
||||||
FontEditor *font_editor;
|
|
||||||
EditorNode *editor;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
virtual String get_name() const { return "Font"; }
|
|
||||||
bool has_main_screen() const { return false; }
|
|
||||||
virtual void edit(Object *p_node);
|
|
||||||
virtual bool handles(Object *p_node) const;
|
|
||||||
virtual void make_visible(bool p_visible);
|
|
||||||
|
|
||||||
FontEditorPlugin(EditorNode *p_node);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif // FONT_EDITOR_PLUGIN_H
|
|
|
@ -73,7 +73,7 @@ void TileSetEditor::_import_scene(Node *scene, Ref<TileSet> p_library, bool p_me
|
||||||
|
|
||||||
p_library->tile_set_texture(id,texture);
|
p_library->tile_set_texture(id,texture);
|
||||||
if (mi->is_centered()) {
|
if (mi->is_centered()) {
|
||||||
p_library->tile_set_offset(id,texture->get_size()/2);
|
p_library->tile_set_texture_offset(id,texture->get_size()/2);
|
||||||
}
|
}
|
||||||
if (mi->is_region()) {
|
if (mi->is_region()) {
|
||||||
p_library->tile_set_region(id,mi->get_region_rect());
|
p_library->tile_set_region(id,mi->get_region_rect());
|
||||||
|
|
Loading…
Reference in a new issue