3D Import Import & UDP
-=-=-=-=-=-=-=-=-=-=- -Animation Import filter support -Animation Clip import support -Animation Optimizer Fixes, Improvements and Visibile Options -Extremely Experimental UDP support.
This commit is contained in:
parent
c8cd5222a7
commit
6dd8768811
|
@ -111,7 +111,7 @@ Variant PacketPeer::_bnd_get_var() const {
|
||||||
void PacketPeer::_bind_methods() {
|
void PacketPeer::_bind_methods() {
|
||||||
|
|
||||||
ObjectTypeDB::bind_method(_MD("get_var"),&PacketPeer::_bnd_get_var);
|
ObjectTypeDB::bind_method(_MD("get_var"),&PacketPeer::_bnd_get_var);
|
||||||
ObjectTypeDB::bind_method(_MD("put_var", "var:Variant"),&PacketPeer::put_var);
|
ObjectTypeDB::bind_method(_MD("put_var", "var:var"),&PacketPeer::put_var);
|
||||||
ObjectTypeDB::bind_method(_MD("get_available_packet_count"),&PacketPeer::get_available_packet_count);
|
ObjectTypeDB::bind_method(_MD("get_available_packet_count"),&PacketPeer::get_available_packet_count);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
#include "packet_peer_udp.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PacketPeerUDP* (*PacketPeerUDP::_create)()=NULL;
|
||||||
|
|
||||||
|
int PacketPeerUDP::_get_packet_address() const {
|
||||||
|
|
||||||
|
IP_Address ip = get_packet_address();
|
||||||
|
return ip.host;
|
||||||
|
}
|
||||||
|
|
||||||
|
String PacketPeerUDP::_get_packet_ip() const {
|
||||||
|
|
||||||
|
return get_packet_address();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PacketPeerUDP::_bind_methods() {
|
||||||
|
|
||||||
|
ObjectTypeDB::bind_method(_MD("listen:Error","port","recv_buf_size"),&PacketPeerUDP::listen,DEFVAL(65536));
|
||||||
|
ObjectTypeDB::bind_method(_MD("close"),&PacketPeerUDP::close);
|
||||||
|
ObjectTypeDB::bind_method(_MD("poll:Error"),&PacketPeerUDP::poll);
|
||||||
|
ObjectTypeDB::bind_method(_MD("is_listening"),&PacketPeerUDP::is_listening);
|
||||||
|
ObjectTypeDB::bind_method(_MD("get_packet_ip"),&PacketPeerUDP::_get_packet_ip);
|
||||||
|
ObjectTypeDB::bind_method(_MD("get_packet_address"),&PacketPeerUDP::_get_packet_address);
|
||||||
|
ObjectTypeDB::bind_method(_MD("set_send_address","address","port"),&PacketPeerUDP::set_send_address);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<PacketPeerUDP> PacketPeerUDP::create_ref() {
|
||||||
|
|
||||||
|
if (!_create)
|
||||||
|
return Ref<PacketPeerUDP>();
|
||||||
|
return Ref<PacketPeerUDP>(_create());
|
||||||
|
}
|
||||||
|
|
||||||
|
PacketPeerUDP* PacketPeerUDP::create() {
|
||||||
|
|
||||||
|
if (!_create)
|
||||||
|
return NULL;
|
||||||
|
return _create();
|
||||||
|
}
|
||||||
|
|
||||||
|
PacketPeerUDP::PacketPeerUDP()
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
#ifndef PACKET_PEER_UDP_H
|
||||||
|
#define PACKET_PEER_UDP_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "io/packet_peer.h"
|
||||||
|
|
||||||
|
class PacketPeerUDP : public PacketPeer {
|
||||||
|
OBJ_TYPE(PacketPeerUDP,PacketPeer);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
static PacketPeerUDP* (*_create)();
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
int _get_packet_address() const;
|
||||||
|
String _get_packet_ip() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual Error listen(int p_port,int p_recv_buffer_size=65536)=0;
|
||||||
|
virtual void close()=0;
|
||||||
|
virtual Error poll()=0;
|
||||||
|
virtual bool is_listening() const=0;
|
||||||
|
virtual IP_Address get_packet_address() const=0;
|
||||||
|
virtual int get_packet_port() const=0;
|
||||||
|
virtual void set_send_address(const IP_Address& p_address,int p_port)=0;
|
||||||
|
|
||||||
|
|
||||||
|
static Ref<PacketPeerUDP> create_ref();
|
||||||
|
static PacketPeerUDP* create();
|
||||||
|
|
||||||
|
PacketPeerUDP();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PACKET_PEER_UDP_H
|
|
@ -29,6 +29,7 @@
|
||||||
#include "register_core_types.h"
|
#include "register_core_types.h"
|
||||||
|
|
||||||
#include "io/tcp_server.h"
|
#include "io/tcp_server.h"
|
||||||
|
#include "io/packet_peer_udp.h"
|
||||||
#include "io/config_file.h"
|
#include "io/config_file.h"
|
||||||
#include "os/main_loop.h"
|
#include "os/main_loop.h"
|
||||||
#include "io/packet_peer.h"
|
#include "io/packet_peer.h"
|
||||||
|
@ -115,6 +116,7 @@ void register_core_types() {
|
||||||
ObjectTypeDB::register_virtual_type<StreamPeer>();
|
ObjectTypeDB::register_virtual_type<StreamPeer>();
|
||||||
ObjectTypeDB::register_create_type<StreamPeerTCP>();
|
ObjectTypeDB::register_create_type<StreamPeerTCP>();
|
||||||
ObjectTypeDB::register_create_type<TCP_Server>();
|
ObjectTypeDB::register_create_type<TCP_Server>();
|
||||||
|
ObjectTypeDB::register_create_type<PacketPeerUDP>();
|
||||||
ObjectTypeDB::register_create_type<StreamPeerSSL>();
|
ObjectTypeDB::register_create_type<StreamPeerSSL>();
|
||||||
ObjectTypeDB::register_virtual_type<IP>();
|
ObjectTypeDB::register_virtual_type<IP>();
|
||||||
ObjectTypeDB::register_virtual_type<PacketPeer>();
|
ObjectTypeDB::register_virtual_type<PacketPeer>();
|
||||||
|
|
|
@ -65,9 +65,9 @@ func _ready():
|
||||||
|
|
||||||
func _exit_tree():
|
func _exit_tree():
|
||||||
for b in bullets:
|
for b in bullets:
|
||||||
Physics2DServer.free(b.body)
|
Physics2DServer.free_rid(b.body)
|
||||||
|
|
||||||
Physics2DServer.free(shape)
|
Physics2DServer.free_rid(shape)
|
||||||
# Initalization here
|
# Initalization here
|
||||||
bullets.clear()
|
bullets.clear()
|
||||||
|
|
||||||
|
|
|
@ -4173,6 +4173,9 @@ void RasterizerGLES2::capture_viewport(Image* r_capture) {
|
||||||
pixels.resize(viewport.width*viewport.height*4);
|
pixels.resize(viewport.width*viewport.height*4);
|
||||||
DVector<uint8_t>::Write w = pixels.write();
|
DVector<uint8_t>::Write w = pixels.write();
|
||||||
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||||
|
|
||||||
|
uint64_t time = OS::get_singleton()->get_ticks_usec();
|
||||||
|
|
||||||
if (current_rt) {
|
if (current_rt) {
|
||||||
#ifdef GLEW_ENABLED
|
#ifdef GLEW_ENABLED
|
||||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||||
|
@ -4182,11 +4185,13 @@ void RasterizerGLES2::capture_viewport(Image* r_capture) {
|
||||||
// back?
|
// back?
|
||||||
glReadPixels( viewport.x, window_size.height-(viewport.height+viewport.y), viewport.width,viewport.height,GL_RGBA,GL_UNSIGNED_BYTE,w.ptr());
|
glReadPixels( viewport.x, window_size.height-(viewport.height+viewport.y), viewport.width,viewport.height,GL_RGBA,GL_UNSIGNED_BYTE,w.ptr());
|
||||||
}
|
}
|
||||||
|
printf("readpixels time %i\n", (int)(OS::get_singleton()->get_ticks_usec() - time));
|
||||||
w=DVector<uint8_t>::Write();
|
w=DVector<uint8_t>::Write();
|
||||||
|
|
||||||
r_capture->create(viewport.width,viewport.height,0,Image::FORMAT_RGBA,pixels);
|
r_capture->create(viewport.width,viewport.height,0,Image::FORMAT_RGBA,pixels);
|
||||||
r_capture->flip_y();
|
r_capture->flip_y();
|
||||||
|
|
||||||
|
printf("total time %i\n", (int)(OS::get_singleton()->get_ticks_usec() - time));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,7 @@ protected:
|
||||||
std::string mName;
|
std::string mName;
|
||||||
int mWidth, mHeight, mStride;
|
int mWidth, mHeight, mStride;
|
||||||
int mNumFrames;
|
int mNumFrames;
|
||||||
|
int audio_track;
|
||||||
|
|
||||||
int mSubFrameWidth, mSubFrameHeight, mSubFrameOffsetX, mSubFrameOffsetY;
|
int mSubFrameWidth, mSubFrameHeight, mSubFrameOffsetX, mSubFrameOffsetY;
|
||||||
float mAudioGain; //! multiplier for audio samples. between 0 and 1
|
float mAudioGain; //! multiplier for audio samples. between 0 and 1
|
||||||
|
@ -233,6 +234,7 @@ public:
|
||||||
bool getAutoRestart() { return mAutoRestart; }
|
bool getAutoRestart() { return mAutoRestart; }
|
||||||
|
|
||||||
|
|
||||||
|
void set_audio_track(int p_track) { audio_track=p_track; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
TODO: user priority. Useful only when more than one video is being decoded
|
TODO: user priority. Useful only when more than one video is being decoded
|
||||||
|
|
|
@ -67,8 +67,8 @@ public:
|
||||||
//! search registered clips by name
|
//! search registered clips by name
|
||||||
TheoraVideoClip* getVideoClipByName(std::string name);
|
TheoraVideoClip* getVideoClipByName(std::string name);
|
||||||
|
|
||||||
TheoraVideoClip* createVideoClip(std::string filename,TheoraOutputMode output_mode=TH_RGB,int numPrecachedOverride=0,bool usePower2Stride=0);
|
TheoraVideoClip* createVideoClip(std::string filename,TheoraOutputMode output_mode=TH_RGB,int numPrecachedOverride=0,bool usePower2Stride=0, int p_track=0);
|
||||||
TheoraVideoClip* createVideoClip(TheoraDataSource* data_source,TheoraOutputMode output_mode=TH_RGB,int numPrecachedOverride=0,bool usePower2Stride=0);
|
TheoraVideoClip* createVideoClip(TheoraDataSource* data_source,TheoraOutputMode output_mode=TH_RGB,int numPrecachedOverride=0,bool usePower2Stride=0, int p_audio_track=0);
|
||||||
|
|
||||||
void update(float timeDelta);
|
void update(float timeDelta);
|
||||||
|
|
||||||
|
|
|
@ -271,7 +271,8 @@ void TheoraVideoClip_AVFoundation::load(TheoraDataSource* source)
|
||||||
AVAssetTrack *videoTrack = [tracks objectAtIndex:0];
|
AVAssetTrack *videoTrack = [tracks objectAtIndex:0];
|
||||||
|
|
||||||
NSArray* audioTracks = [asset tracksWithMediaType:AVMediaTypeAudio];
|
NSArray* audioTracks = [asset tracksWithMediaType:AVMediaTypeAudio];
|
||||||
AVAssetTrack *audioTrack = audioTracks.count > 0 ? [audioTracks objectAtIndex:0] : NULL;
|
AVAssetTrack *audioTrack = audioTracks.count > 0 ? [audioTracks objectAtIndex:audio_track] : NULL;
|
||||||
|
printf("*********** using audio track %i\n", audio_track);
|
||||||
|
|
||||||
#ifdef _AVFOUNDATION_BGRX
|
#ifdef _AVFOUNDATION_BGRX
|
||||||
bool yuv_output = (mOutputMode != TH_BGRX && mOutputMode != TH_RGBA);
|
bool yuv_output = (mOutputMode != TH_BGRX && mOutputMode != TH_RGBA);
|
||||||
|
|
|
@ -51,6 +51,8 @@ TheoraVideoClip::TheoraVideoClip(TheoraDataSource* data_source,
|
||||||
mWaitingForCache(false),
|
mWaitingForCache(false),
|
||||||
mOutputMode(TH_UNDEFINED)
|
mOutputMode(TH_UNDEFINED)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
audio_track=0;
|
||||||
mAudioMutex = NULL;
|
mAudioMutex = NULL;
|
||||||
mThreadAccessMutex = new TheoraMutex();
|
mThreadAccessMutex = new TheoraMutex();
|
||||||
mTimer = mDefaultTimer = new TheoraTimer();
|
mTimer = mDefaultTimer = new TheoraTimer();
|
||||||
|
|
|
@ -35,6 +35,8 @@ extern "C"
|
||||||
void initYUVConversionModule();
|
void initYUVConversionModule();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "core/os/memory.h"
|
||||||
|
|
||||||
//#define _DECODING_BENCHMARK //uncomment to test average decoding time on a given device
|
//#define _DECODING_BENCHMARK //uncomment to test average decoding time on a given device
|
||||||
|
|
||||||
|
|
||||||
|
@ -184,16 +186,18 @@ TheoraAudioInterfaceFactory* TheoraVideoManager::getAudioInterfaceFactory()
|
||||||
TheoraVideoClip* TheoraVideoManager::createVideoClip(std::string filename,
|
TheoraVideoClip* TheoraVideoManager::createVideoClip(std::string filename,
|
||||||
TheoraOutputMode output_mode,
|
TheoraOutputMode output_mode,
|
||||||
int numPrecachedOverride,
|
int numPrecachedOverride,
|
||||||
bool usePower2Stride)
|
bool usePower2Stride,
|
||||||
|
int p_track)
|
||||||
{
|
{
|
||||||
TheoraDataSource* src=new TheoraFileDataSource(filename);
|
TheoraDataSource* src=memnew(TheoraFileDataSource(filename));
|
||||||
return createVideoClip(src,output_mode,numPrecachedOverride,usePower2Stride);
|
return createVideoClip(src,output_mode,numPrecachedOverride,usePower2Stride, p_track);
|
||||||
}
|
}
|
||||||
|
|
||||||
TheoraVideoClip* TheoraVideoManager::createVideoClip(TheoraDataSource* data_source,
|
TheoraVideoClip* TheoraVideoManager::createVideoClip(TheoraDataSource* data_source,
|
||||||
TheoraOutputMode output_mode,
|
TheoraOutputMode output_mode,
|
||||||
int numPrecachedOverride,
|
int numPrecachedOverride,
|
||||||
bool usePower2Stride)
|
bool usePower2Stride,
|
||||||
|
int p_audio_track)
|
||||||
{
|
{
|
||||||
mWorkMutex->lock();
|
mWorkMutex->lock();
|
||||||
|
|
||||||
|
@ -226,6 +230,8 @@ TheoraVideoClip* TheoraVideoManager::createVideoClip(TheoraDataSource* data_sour
|
||||||
#ifdef __FFMPEG
|
#ifdef __FFMPEG
|
||||||
clip = new TheoraVideoClip_FFmpeg(data_source, output_mode, nPrecached, usePower2Stride);
|
clip = new TheoraVideoClip_FFmpeg(data_source, output_mode, nPrecached, usePower2Stride);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
clip->set_audio_track(p_audio_track);
|
||||||
clip->load(data_source);
|
clip->load(data_source);
|
||||||
clip->decodeNextFrame(); // ensure the first frame is always preloaded and have the main thread do it to prevent potential thread starvatio
|
clip->decodeNextFrame(); // ensure the first frame is always preloaded and have the main thread do it to prevent potential thread starvatio
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,8 @@
|
||||||
#include "core/ring_buffer.h"
|
#include "core/ring_buffer.h"
|
||||||
#include "core/os/thread_safe.h"
|
#include "core/os/thread_safe.h"
|
||||||
|
|
||||||
|
#include "core/globals.h"
|
||||||
|
|
||||||
static TheoraVideoManager* mgr = NULL;
|
static TheoraVideoManager* mgr = NULL;
|
||||||
|
|
||||||
class TPDataFA : public TheoraDataSource {
|
class TPDataFA : public TheoraDataSource {
|
||||||
|
@ -141,6 +143,7 @@ public:
|
||||||
playing=false;
|
playing=false;
|
||||||
_clear();
|
_clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual bool is_playing() const { return true; };
|
virtual bool is_playing() const { return true; };
|
||||||
|
|
||||||
virtual void set_paused(bool p_paused) {};
|
virtual void set_paused(bool p_paused) {};
|
||||||
|
@ -164,12 +167,16 @@ public:
|
||||||
|
|
||||||
void input(float* p_data, int p_samples) {
|
void input(float* p_data, int p_samples) {
|
||||||
|
|
||||||
|
|
||||||
_THREAD_SAFE_METHOD_;
|
_THREAD_SAFE_METHOD_;
|
||||||
|
//printf("input %i samples from %p\n", p_samples, p_data);
|
||||||
if (rb.space_left() < p_samples) {
|
if (rb.space_left() < p_samples) {
|
||||||
rb_power += 1;
|
rb_power += 1;
|
||||||
rb.resize(rb_power);
|
rb.resize(rb_power);
|
||||||
}
|
}
|
||||||
rb.write(p_data, p_samples);
|
rb.write(p_data, p_samples);
|
||||||
|
|
||||||
|
update(); //update too here for less latency
|
||||||
};
|
};
|
||||||
|
|
||||||
void update() {
|
void update() {
|
||||||
|
@ -177,15 +184,16 @@ public:
|
||||||
_THREAD_SAFE_METHOD_;
|
_THREAD_SAFE_METHOD_;
|
||||||
int todo = get_todo();
|
int todo = get_todo();
|
||||||
int16_t* buffer = get_write_buffer();
|
int16_t* buffer = get_write_buffer();
|
||||||
int samples = rb.data_left();
|
int frames = rb.data_left()/channels;
|
||||||
const int to_write = MIN(todo, samples);
|
const int to_write = MIN(todo, frames);
|
||||||
|
|
||||||
for (int i=0; i<to_write; i++) {
|
for (int i=0; i<to_write*channels; i++) {
|
||||||
|
|
||||||
uint16_t sample = uint16_t(rb.read() * 32767);
|
int v = rb.read() * 32767;
|
||||||
|
int16_t sample = CLAMP(v,-32768,32767);
|
||||||
buffer[i] = sample;
|
buffer[i] = sample;
|
||||||
};
|
};
|
||||||
write(to_write/channels);
|
write(to_write);
|
||||||
total_wrote += to_write;
|
total_wrote += to_write;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -231,7 +239,7 @@ public:
|
||||||
TPAudioGodot(TheoraVideoClip* owner, int nChannels, int p_freq)
|
TPAudioGodot(TheoraVideoClip* owner, int nChannels, int p_freq)
|
||||||
: TheoraAudioInterface(owner, nChannels, p_freq), TheoraTimer() {
|
: TheoraAudioInterface(owner, nChannels, p_freq), TheoraTimer() {
|
||||||
|
|
||||||
printf("***************** audio interface constructor\n");
|
printf("***************** audio interface constructor freq %i\n", p_freq);
|
||||||
channels = nChannels;
|
channels = nChannels;
|
||||||
freq = p_freq;
|
freq = p_freq;
|
||||||
stream = Ref<AudioStreamInput>(memnew(AudioStreamInput(nChannels, p_freq)));
|
stream = Ref<AudioStreamInput>(memnew(AudioStreamInput(nChannels, p_freq)));
|
||||||
|
@ -247,12 +255,13 @@ public:
|
||||||
|
|
||||||
void update(float time_increase)
|
void update(float time_increase)
|
||||||
{
|
{
|
||||||
mTime = (float)(stream->get_total_wrote() / channels) / freq;
|
//mTime = (float)(stream->get_total_wrote()) / freq;
|
||||||
|
//mTime = MAX(0,mTime-AudioServer::get_singleton()->get_output_delay());
|
||||||
//mTime = (float)sample_count / channels / freq;
|
//mTime = (float)sample_count / channels / freq;
|
||||||
//mTime += time_increase;
|
mTime += time_increase;
|
||||||
//float duration=mClip->getDuration();
|
//float duration=mClip->getDuration();
|
||||||
//if (mTime > duration) mTime=duration;
|
//if (mTime > duration) mTime=duration;
|
||||||
//printf("time at timer is %f, samples %i\n", mTime, sample_count);
|
//printf("time at timer is %f, %f, samples %i\n", mTime, time_increase, sample_count);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -358,13 +367,15 @@ void VideoStreamTheoraplayer::pop_frame(Ref<ImageTexture> p_tex) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float w=clip->getWidth(),h=clip->getHeight();
|
float w=clip->getWidth(),h=clip->getHeight();
|
||||||
int imgsize = w * h * f->mBpp;
|
int imgsize = w * h * f->mBpp;
|
||||||
|
|
||||||
int size = f->getStride() * f->getHeight() * f->mBpp;
|
int size = f->getStride() * f->getHeight() * f->mBpp;
|
||||||
data.resize(imgsize);
|
data.resize(imgsize);
|
||||||
DVector<uint8_t>::Write wr = data.write();
|
{
|
||||||
uint8_t* ptr = wr.ptr();
|
DVector<uint8_t>::Write wr = data.write();
|
||||||
copymem(ptr, f->getBuffer(), imgsize);
|
uint8_t* ptr = wr.ptr();
|
||||||
|
memcpy(ptr, f->getBuffer(), imgsize);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
for (int i=0; i<h; i++) {
|
for (int i=0; i<h; i++) {
|
||||||
int dstofs = i * w * f->mBpp;
|
int dstofs = i * w * f->mBpp;
|
||||||
|
@ -421,6 +432,13 @@ void VideoStreamTheoraplayer::update(float p_time) {
|
||||||
mgr->update(p_time);
|
mgr->update(p_time);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void VideoStreamTheoraplayer::set_audio_track(int p_idx) {
|
||||||
|
audio_track=p_idx;
|
||||||
|
if (clip)
|
||||||
|
clip->set_audio_track(audio_track);
|
||||||
|
}
|
||||||
|
|
||||||
void VideoStreamTheoraplayer::set_file(const String& p_file) {
|
void VideoStreamTheoraplayer::set_file(const String& p_file) {
|
||||||
|
|
||||||
FileAccess* f = FileAccess::open(p_file, FileAccess::READ);
|
FileAccess* f = FileAccess::open(p_file, FileAccess::READ);
|
||||||
|
@ -436,10 +454,13 @@ void VideoStreamTheoraplayer::set_file(const String& p_file) {
|
||||||
mgr->setAudioInterfaceFactory(audio_factory);
|
mgr->setAudioInterfaceFactory(audio_factory);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int track = GLOBAL_DEF("theora/audio_track", 0); // hack
|
||||||
|
|
||||||
if (p_file.find(".mp4") != -1) {
|
if (p_file.find(".mp4") != -1) {
|
||||||
|
|
||||||
std::string file = p_file.replace("res://", "").utf8().get_data();
|
std::string file = p_file.replace("res://", "").utf8().get_data();
|
||||||
clip = mgr->createVideoClip(file, TH_BGRX, 16);
|
clip = mgr->createVideoClip(file, TH_RGBX, 2, false, track);
|
||||||
|
//clip->set_audio_track(audio_track);
|
||||||
memdelete(f);
|
memdelete(f);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -448,6 +469,7 @@ void VideoStreamTheoraplayer::set_file(const String& p_file) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
clip = mgr->createVideoClip(ds);
|
clip = mgr->createVideoClip(ds);
|
||||||
|
clip->set_audio_track(audio_track);
|
||||||
} catch (_TheoraGenericException e) {
|
} catch (_TheoraGenericException e) {
|
||||||
printf("exception ocurred! %s\n", e.repr().c_str());
|
printf("exception ocurred! %s\n", e.repr().c_str());
|
||||||
clip = NULL;
|
clip = NULL;
|
||||||
|
@ -478,6 +500,7 @@ VideoStreamTheoraplayer::VideoStreamTheoraplayer() {
|
||||||
started = false;
|
started = false;
|
||||||
playing = false;
|
playing = false;
|
||||||
loop = false;
|
loop = false;
|
||||||
|
audio_track=0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class VideoStreamTheoraplayer : public VideoStream {
|
||||||
bool playing;
|
bool playing;
|
||||||
bool loop;
|
bool loop;
|
||||||
|
|
||||||
|
int audio_track;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void stop();
|
virtual void stop();
|
||||||
|
@ -43,6 +45,7 @@ public:
|
||||||
void update(float p_time);
|
void update(float p_time);
|
||||||
|
|
||||||
void set_file(const String& p_file);
|
void set_file(const String& p_file);
|
||||||
|
void set_audio_track(int p_idx);
|
||||||
|
|
||||||
~VideoStreamTheoraplayer();
|
~VideoStreamTheoraplayer();
|
||||||
VideoStreamTheoraplayer();
|
VideoStreamTheoraplayer();
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include "dir_access_unix.h"
|
#include "dir_access_unix.h"
|
||||||
#include "tcp_server_posix.h"
|
#include "tcp_server_posix.h"
|
||||||
#include "stream_peer_tcp_posix.h"
|
#include "stream_peer_tcp_posix.h"
|
||||||
|
#include "packet_peer_udp_posix.h"
|
||||||
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
@ -115,6 +116,7 @@ void OS_Unix::initialize_core() {
|
||||||
#ifndef NO_NETWORK
|
#ifndef NO_NETWORK
|
||||||
TCPServerPosix::make_default();
|
TCPServerPosix::make_default();
|
||||||
StreamPeerTCPPosix::make_default();
|
StreamPeerTCPPosix::make_default();
|
||||||
|
PacketPeerUDPPosix::make_default();
|
||||||
IP_Unix::make_default();
|
IP_Unix::make_default();
|
||||||
#endif
|
#endif
|
||||||
mempool_static = new MemoryPoolStaticMalloc;
|
mempool_static = new MemoryPoolStaticMalloc;
|
||||||
|
|
|
@ -0,0 +1,188 @@
|
||||||
|
#include "packet_peer_udp_posix.h"
|
||||||
|
|
||||||
|
#ifdef UNIX_ENABLED
|
||||||
|
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifndef NO_FCNTL
|
||||||
|
#include <sys/fcntl.h>
|
||||||
|
#else
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef JAVASCRIPT_ENABLED
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
int PacketPeerUDPPosix::get_available_packet_count() const {
|
||||||
|
|
||||||
|
Error err = const_cast<PacketPeerUDPPosix*>(this)->poll();
|
||||||
|
if (err!=OK)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return queue_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error PacketPeerUDPPosix::get_packet(const uint8_t **r_buffer,int &r_buffer_size) const{
|
||||||
|
|
||||||
|
Error err = const_cast<PacketPeerUDPPosix*>(this)->poll();
|
||||||
|
if (err!=OK)
|
||||||
|
return err;
|
||||||
|
if (queue_count==0)
|
||||||
|
return ERR_UNAVAILABLE;
|
||||||
|
|
||||||
|
uint32_t size;
|
||||||
|
rb.read((uint8_t*)&size,4,true);
|
||||||
|
rb.read((uint8_t*)&packet_ip.host,4,true);
|
||||||
|
rb.read((uint8_t*)&packet_port,4,true);
|
||||||
|
rb.read(packet_buffer,size,true);
|
||||||
|
--queue_count;
|
||||||
|
*r_buffer=packet_buffer;
|
||||||
|
r_buffer_size=size;
|
||||||
|
return OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
Error PacketPeerUDPPosix::put_packet(const uint8_t *p_buffer,int p_buffer_size){
|
||||||
|
|
||||||
|
int sock = _get_socket();
|
||||||
|
ERR_FAIL_COND_V( sock == -1, FAILED );
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(peer_port);
|
||||||
|
addr.sin_addr = *((struct in_addr*)&peer_addr.host);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
int err;
|
||||||
|
while ( (err = sendto(sock, p_buffer, p_buffer_size, 0, (struct sockaddr*)&addr, sizeof(addr))) != p_buffer_size) {
|
||||||
|
|
||||||
|
if (errno != EAGAIN) {
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PacketPeerUDPPosix::get_max_packet_size() const{
|
||||||
|
|
||||||
|
return 512; // uhm maybe not
|
||||||
|
}
|
||||||
|
|
||||||
|
Error PacketPeerUDPPosix::listen(int p_port, int p_recv_buffer_size){
|
||||||
|
|
||||||
|
close();
|
||||||
|
int sock = _get_socket();
|
||||||
|
if (sock == -1 )
|
||||||
|
return ERR_CANT_CREATE;
|
||||||
|
sockaddr_in addr = {0};
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(p_port);
|
||||||
|
addr.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
if (bind(sock, (struct sockaddr*)&addr, sizeof(sockaddr_in)) == -1 ) {
|
||||||
|
close();
|
||||||
|
return ERR_UNAVAILABLE;
|
||||||
|
}
|
||||||
|
printf("UDP Connection listening on port %i\n", p_port);
|
||||||
|
rb.resize(nearest_power_of_2(p_recv_buffer_size));
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PacketPeerUDPPosix::close(){
|
||||||
|
|
||||||
|
if (sockfd != -1)
|
||||||
|
::close(sockfd);
|
||||||
|
sockfd=-1;
|
||||||
|
rb.resize(8);
|
||||||
|
queue_count=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error PacketPeerUDPPosix::poll() {
|
||||||
|
|
||||||
|
struct sockaddr_in from = {0};
|
||||||
|
socklen_t len = sizeof(struct sockaddr_in);
|
||||||
|
int ret;
|
||||||
|
while ( (ret = recvfrom(sockfd, recv_buffer, MIN(sizeof(recv_buffer),rb.data_left()-12), MSG_DONTWAIT, (struct sockaddr*)&from, &len)) > 0) {
|
||||||
|
rb.write((uint8_t*)&from.sin_addr, 4);
|
||||||
|
uint32_t port = ntohs(from.sin_port);
|
||||||
|
rb.write((uint8_t*)&port, 4);
|
||||||
|
rb.write((uint8_t*)&ret, 4);
|
||||||
|
rb.write(recv_buffer, ret);
|
||||||
|
|
||||||
|
len = sizeof(struct sockaddr_in);
|
||||||
|
++queue_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (ret == 0 || (ret == -1 && errno != EAGAIN) ) {
|
||||||
|
close();
|
||||||
|
return FAILED;
|
||||||
|
};
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
bool PacketPeerUDPPosix::is_listening() const{
|
||||||
|
|
||||||
|
return sockfd!=-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
IP_Address PacketPeerUDPPosix::get_packet_address() const {
|
||||||
|
|
||||||
|
return packet_ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PacketPeerUDPPosix::get_packet_port() const{
|
||||||
|
|
||||||
|
return packet_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PacketPeerUDPPosix::_get_socket() {
|
||||||
|
|
||||||
|
if (sockfd != -1)
|
||||||
|
return sockfd;
|
||||||
|
|
||||||
|
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
ERR_FAIL_COND_V( sockfd == -1, -1 );
|
||||||
|
//fcntl(sockfd, F_SETFL, O_NONBLOCK);
|
||||||
|
|
||||||
|
return sockfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PacketPeerUDPPosix::set_send_address(const IP_Address& p_address,int p_port) {
|
||||||
|
|
||||||
|
peer_addr=p_address;
|
||||||
|
peer_port=p_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
PacketPeerUDP* PacketPeerUDPPosix::_create() {
|
||||||
|
|
||||||
|
return memnew(PacketPeerUDPPosix);
|
||||||
|
};
|
||||||
|
|
||||||
|
void PacketPeerUDPPosix::make_default() {
|
||||||
|
|
||||||
|
PacketPeerUDP::_create = PacketPeerUDPPosix::_create;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
PacketPeerUDPPosix::PacketPeerUDPPosix() {
|
||||||
|
|
||||||
|
sockfd=-1;
|
||||||
|
packet_port=0;
|
||||||
|
queue_count=0;
|
||||||
|
peer_port=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PacketPeerUDPPosix::~PacketPeerUDPPosix() {
|
||||||
|
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,56 @@
|
||||||
|
#ifndef PACKET_PEER_UDP_POSIX_H
|
||||||
|
#define PACKET_PEER_UDP_POSIX_H
|
||||||
|
|
||||||
|
#ifdef UNIX_ENABLED
|
||||||
|
|
||||||
|
#include "io/packet_peer_udp.h"
|
||||||
|
#include "ring_buffer.h"
|
||||||
|
|
||||||
|
class PacketPeerUDPPosix : public PacketPeerUDP {
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PACKET_BUFFER_SIZE=65536
|
||||||
|
};
|
||||||
|
|
||||||
|
mutable RingBuffer<uint8_t> rb;
|
||||||
|
uint8_t recv_buffer[PACKET_BUFFER_SIZE];
|
||||||
|
mutable uint8_t packet_buffer[PACKET_BUFFER_SIZE];
|
||||||
|
IP_Address packet_ip;
|
||||||
|
int packet_port;
|
||||||
|
mutable int queue_count;
|
||||||
|
int sockfd;
|
||||||
|
|
||||||
|
IP_Address peer_addr;
|
||||||
|
int peer_port;
|
||||||
|
|
||||||
|
_FORCE_INLINE_ int _get_socket();
|
||||||
|
|
||||||
|
static PacketPeerUDP* _create();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual int get_available_packet_count() const;
|
||||||
|
virtual Error get_packet(const uint8_t **r_buffer,int &r_buffer_size) const;
|
||||||
|
virtual Error put_packet(const uint8_t *p_buffer,int p_buffer_size);
|
||||||
|
|
||||||
|
virtual int get_max_packet_size() const;
|
||||||
|
|
||||||
|
virtual Error listen(int p_port,int p_recv_buffer_size=65536);
|
||||||
|
virtual void close();
|
||||||
|
virtual Error poll();
|
||||||
|
virtual bool is_listening() const;
|
||||||
|
|
||||||
|
virtual IP_Address get_packet_address() const;
|
||||||
|
virtual int get_packet_port() const;
|
||||||
|
|
||||||
|
virtual void set_send_address(const IP_Address& p_address,int p_port);
|
||||||
|
|
||||||
|
static void make_default();
|
||||||
|
|
||||||
|
PacketPeerUDPPosix();
|
||||||
|
~PacketPeerUDPPosix();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PACKET_PEER_UDP_POSIX_H
|
||||||
|
#endif
|
|
@ -1533,7 +1533,7 @@ EditorExportPlatformAndroid::EditorExportPlatformAndroid() {
|
||||||
device_lock = Mutex::create();
|
device_lock = Mutex::create();
|
||||||
quit_request=false;
|
quit_request=false;
|
||||||
orientation=0;
|
orientation=0;
|
||||||
remove_prev=false;
|
remove_prev=true;
|
||||||
|
|
||||||
device_thread=Thread::create(_device_poll_thread,this);
|
device_thread=Thread::create(_device_poll_thread,this);
|
||||||
devices_changed=true;
|
devices_changed=true;
|
||||||
|
|
|
@ -7,6 +7,7 @@ common_win=[
|
||||||
"ctxgl_procaddr.cpp",
|
"ctxgl_procaddr.cpp",
|
||||||
"key_mapping_win.cpp",
|
"key_mapping_win.cpp",
|
||||||
"tcp_server_winsock.cpp",
|
"tcp_server_winsock.cpp",
|
||||||
|
"packet_peer_udp_winsock.cpp",
|
||||||
"stream_peer_winsock.cpp",
|
"stream_peer_winsock.cpp",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
#include "servers/visual/visual_server_wrap_mt.h"
|
#include "servers/visual/visual_server_wrap_mt.h"
|
||||||
|
|
||||||
#include "tcp_server_winsock.h"
|
#include "tcp_server_winsock.h"
|
||||||
|
#include "packet_peer_udp_winsock.h"
|
||||||
#include "stream_peer_winsock.h"
|
#include "stream_peer_winsock.h"
|
||||||
#include "os/pc_joystick_map.h"
|
#include "os/pc_joystick_map.h"
|
||||||
#include "lang_table.h"
|
#include "lang_table.h"
|
||||||
|
@ -173,6 +174,7 @@ void OS_Windows::initialize_core() {
|
||||||
|
|
||||||
TCPServerWinsock::make_default();
|
TCPServerWinsock::make_default();
|
||||||
StreamPeerWinsock::make_default();
|
StreamPeerWinsock::make_default();
|
||||||
|
PacketPeerUDPWinsock::make_default();
|
||||||
|
|
||||||
mempool_static = new MemoryPoolStaticMalloc;
|
mempool_static = new MemoryPoolStaticMalloc;
|
||||||
#if 1
|
#if 1
|
||||||
|
|
|
@ -0,0 +1,167 @@
|
||||||
|
#include "packet_peer_udp_winsock.h"
|
||||||
|
|
||||||
|
#include <winsock2.h>
|
||||||
|
|
||||||
|
int PacketPeerUDPWinsock::get_available_packet_count() const {
|
||||||
|
|
||||||
|
Error err = const_cast<PacketPeerUDPWinsock*>(this)->poll();
|
||||||
|
if (err!=OK)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return queue_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error PacketPeerUDPWinsock::get_packet(const uint8_t **r_buffer,int &r_buffer_size) const{
|
||||||
|
|
||||||
|
Error err = const_cast<PacketPeerUDPWinsock*>(this)->poll();
|
||||||
|
if (err!=OK)
|
||||||
|
return err;
|
||||||
|
if (queue_count==0)
|
||||||
|
return ERR_UNAVAILABLE;
|
||||||
|
|
||||||
|
uint32_t size;
|
||||||
|
rb.read((uint8_t*)&size,4,true);
|
||||||
|
rb.read((uint8_t*)&packet_ip.host,4,true);
|
||||||
|
rb.read((uint8_t*)&packet_port,4,true);
|
||||||
|
rb.read(packet_buffer,size,true);
|
||||||
|
--queue_count;
|
||||||
|
*r_buffer=packet_buffer;
|
||||||
|
r_buffer_size=size;
|
||||||
|
return OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
Error PacketPeerUDPWinsock::put_packet(const uint8_t *p_buffer,int p_buffer_size){
|
||||||
|
|
||||||
|
int sock = _get_socket();
|
||||||
|
ERR_FAIL_COND_V( sock == -1, FAILED );
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(peer_port);
|
||||||
|
addr.sin_addr = *((struct in_addr*)&peer_addr.host);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
int err;
|
||||||
|
while ( (err = sendto(sock, (const char*)p_buffer, p_buffer_size, 0, (struct sockaddr*)&addr, sizeof(addr))) != p_buffer_size) {
|
||||||
|
|
||||||
|
if (WSAGetLastError() != WSAEWOULDBLOCK) {
|
||||||
|
return FAILED;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PacketPeerUDPWinsock::get_max_packet_size() const{
|
||||||
|
|
||||||
|
return 512; // uhm maybe not
|
||||||
|
}
|
||||||
|
|
||||||
|
Error PacketPeerUDPWinsock::listen(int p_port, int p_recv_buffer_size){
|
||||||
|
|
||||||
|
close();
|
||||||
|
int sock = _get_socket();
|
||||||
|
if (sock == -1 )
|
||||||
|
return ERR_CANT_CREATE;
|
||||||
|
sockaddr_in addr = {0};
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(p_port);
|
||||||
|
addr.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
if (bind(sock, (struct sockaddr*)&addr, sizeof(sockaddr_in)) == -1 ) {
|
||||||
|
close();
|
||||||
|
return ERR_UNAVAILABLE;
|
||||||
|
}
|
||||||
|
printf("UDP Connection listening on port %i\n", p_port);
|
||||||
|
rb.resize(nearest_power_of_2(p_recv_buffer_size));
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PacketPeerUDPWinsock::close(){
|
||||||
|
|
||||||
|
if (sockfd != -1)
|
||||||
|
::closesocket(sockfd);
|
||||||
|
sockfd=-1;
|
||||||
|
rb.resize(8);
|
||||||
|
queue_count=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error PacketPeerUDPWinsock::poll() {
|
||||||
|
|
||||||
|
struct sockaddr_in from = {0};
|
||||||
|
int len = sizeof(struct sockaddr_in);
|
||||||
|
int ret;
|
||||||
|
while ( (ret = recvfrom(sockfd, (char*)recv_buffer, MIN(sizeof(recv_buffer),rb.data_left()-12), 0, (struct sockaddr*)&from, &len)) > 0) {
|
||||||
|
rb.write((uint8_t*)&from.sin_addr, 4);
|
||||||
|
uint32_t port = ntohs(from.sin_port);
|
||||||
|
rb.write((uint8_t*)&port, 4);
|
||||||
|
rb.write((uint8_t*)&ret, 4);
|
||||||
|
rb.write(recv_buffer, ret);
|
||||||
|
|
||||||
|
len = sizeof(struct sockaddr_in);
|
||||||
|
++queue_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) ) {
|
||||||
|
close();
|
||||||
|
return FAILED;
|
||||||
|
};
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
bool PacketPeerUDPWinsock::is_listening() const{
|
||||||
|
|
||||||
|
return sockfd!=-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
IP_Address PacketPeerUDPWinsock::get_packet_address() const {
|
||||||
|
|
||||||
|
return packet_ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PacketPeerUDPWinsock::get_packet_port() const{
|
||||||
|
|
||||||
|
return packet_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PacketPeerUDPWinsock::_get_socket() {
|
||||||
|
|
||||||
|
if (sockfd != -1)
|
||||||
|
return sockfd;
|
||||||
|
|
||||||
|
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
ERR_FAIL_COND_V( sockfd == -1, -1 );
|
||||||
|
//fcntl(sockfd, F_SETFL, O_NONBLOCK);
|
||||||
|
|
||||||
|
return sockfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PacketPeerUDPWinsock::set_send_address(const IP_Address& p_address,int p_port) {
|
||||||
|
|
||||||
|
peer_addr=p_address;
|
||||||
|
peer_port=p_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PacketPeerUDPWinsock::make_default() {
|
||||||
|
|
||||||
|
PacketPeerUDP::_create = PacketPeerUDPWinsock::_create;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
PacketPeerUDP* PacketPeerUDPWinsock::_create() {
|
||||||
|
|
||||||
|
return memnew(PacketPeerUDPWinsock);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
PacketPeerUDPWinsock::PacketPeerUDPWinsock() {
|
||||||
|
|
||||||
|
sockfd=-1;
|
||||||
|
packet_port=0;
|
||||||
|
queue_count=0;
|
||||||
|
peer_port=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PacketPeerUDPWinsock::~PacketPeerUDPWinsock() {
|
||||||
|
|
||||||
|
close();
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
#ifndef PACKET_PEER_UDP_WINSOCK_H
|
||||||
|
#define PACKET_PEER_UDP_WINSOCK_H
|
||||||
|
|
||||||
|
#include "io/packet_peer_udp.h"
|
||||||
|
#include "ring_buffer.h"
|
||||||
|
|
||||||
|
class PacketPeerUDPWinsock : public PacketPeerUDP {
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PACKET_BUFFER_SIZE=65536
|
||||||
|
};
|
||||||
|
|
||||||
|
mutable RingBuffer<uint8_t> rb;
|
||||||
|
uint8_t recv_buffer[PACKET_BUFFER_SIZE];
|
||||||
|
mutable uint8_t packet_buffer[PACKET_BUFFER_SIZE];
|
||||||
|
IP_Address packet_ip;
|
||||||
|
int packet_port;
|
||||||
|
mutable int queue_count;
|
||||||
|
int sockfd;
|
||||||
|
|
||||||
|
IP_Address peer_addr;
|
||||||
|
int peer_port;
|
||||||
|
|
||||||
|
_FORCE_INLINE_ int _get_socket();
|
||||||
|
|
||||||
|
static PacketPeerUDP* _create();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual int get_available_packet_count() const;
|
||||||
|
virtual Error get_packet(const uint8_t **r_buffer,int &r_buffer_size) const;
|
||||||
|
virtual Error put_packet(const uint8_t *p_buffer,int p_buffer_size);
|
||||||
|
|
||||||
|
virtual int get_max_packet_size() const;
|
||||||
|
|
||||||
|
virtual Error listen(int p_port,int p_recv_buffer_size=65536);
|
||||||
|
virtual void close();
|
||||||
|
virtual Error poll();
|
||||||
|
virtual bool is_listening() const;
|
||||||
|
|
||||||
|
virtual IP_Address get_packet_address() const;
|
||||||
|
virtual int get_packet_port() const;
|
||||||
|
|
||||||
|
virtual void set_send_address(const IP_Address& p_address,int p_port);
|
||||||
|
|
||||||
|
static void make_default();
|
||||||
|
PacketPeerUDPWinsock();
|
||||||
|
~PacketPeerUDPWinsock();
|
||||||
|
};
|
||||||
|
#endif // PACKET_PEER_UDP_WINSOCK_H
|
|
@ -55,9 +55,9 @@ void BaseButton::_input_event(InputEvent p_event) {
|
||||||
if (b.pressed) {
|
if (b.pressed) {
|
||||||
|
|
||||||
if (!toggle_mode) { //mouse press attempt
|
if (!toggle_mode) { //mouse press attempt
|
||||||
|
|
||||||
status.press_attempt=true;
|
status.press_attempt=true;
|
||||||
status.pressing_inside=true;
|
status.pressing_inside=true;
|
||||||
|
|
||||||
pressed();
|
pressed();
|
||||||
emit_signal("pressed");
|
emit_signal("pressed");
|
||||||
|
@ -74,13 +74,13 @@ void BaseButton::_input_event(InputEvent p_event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (status.press_attempt &&status.pressing_inside) {
|
if (status.press_attempt && status.pressing_inside) {
|
||||||
pressed();
|
// released();
|
||||||
emit_signal("pressed");
|
emit_signal("released");
|
||||||
}
|
}
|
||||||
status.press_attempt=false;
|
status.press_attempt=false;
|
||||||
}
|
}
|
||||||
update();
|
update();
|
||||||
break;
|
break;
|
||||||
|
@ -95,14 +95,14 @@ void BaseButton::_input_event(InputEvent p_event) {
|
||||||
|
|
||||||
|
|
||||||
if (status.press_attempt &&status.pressing_inside) {
|
if (status.press_attempt &&status.pressing_inside) {
|
||||||
|
|
||||||
if (!toggle_mode) { //mouse press attempt
|
if (!toggle_mode) { //mouse press attempt
|
||||||
|
|
||||||
pressed();
|
pressed();
|
||||||
emit_signal("pressed");
|
emit_signal("pressed");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
status.pressed=!status.pressed;
|
status.pressed=!status.pressed;
|
||||||
|
|
||||||
pressed();
|
pressed();
|
||||||
|
@ -110,11 +110,11 @@ void BaseButton::_input_event(InputEvent p_event) {
|
||||||
|
|
||||||
toggled(status.pressed);
|
toggled(status.pressed);
|
||||||
emit_signal("toggled",status.pressed);
|
emit_signal("toggled",status.pressed);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
status.press_attempt=false;
|
status.press_attempt=false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -363,6 +363,7 @@ void BaseButton::_bind_methods() {
|
||||||
ObjectTypeDB::bind_method(_MD("get_draw_mode"),&BaseButton::get_draw_mode);
|
ObjectTypeDB::bind_method(_MD("get_draw_mode"),&BaseButton::get_draw_mode);
|
||||||
|
|
||||||
ADD_SIGNAL( MethodInfo("pressed" ) );
|
ADD_SIGNAL( MethodInfo("pressed" ) );
|
||||||
|
ADD_SIGNAL( MethodInfo("released" ) );
|
||||||
ADD_SIGNAL( MethodInfo("toggled", PropertyInfo( Variant::BOOL,"pressed") ) );
|
ADD_SIGNAL( MethodInfo("toggled", PropertyInfo( Variant::BOOL,"pressed") ) );
|
||||||
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "disabled"), _SCS("set_disabled"), _SCS("is_disabled"));
|
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "disabled"), _SCS("set_disabled"), _SCS("is_disabled"));
|
||||||
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "toggle_mode"), _SCS("set_toggle_mode"), _SCS("is_toggle_mode"));
|
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "toggle_mode"), _SCS("set_toggle_mode"), _SCS("is_toggle_mode"));
|
||||||
|
|
|
@ -192,7 +192,7 @@ String VideoPlayer::get_stream_name() const {
|
||||||
return stream->get_name();
|
return stream->get_name();
|
||||||
};
|
};
|
||||||
|
|
||||||
float VideoPlayer::get_pos() const {
|
float VideoPlayer::get_stream_pos() const {
|
||||||
|
|
||||||
if (stream.is_null())
|
if (stream.is_null())
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -231,7 +231,7 @@ void VideoPlayer::_bind_methods() {
|
||||||
|
|
||||||
ObjectTypeDB::bind_method(_MD("get_stream_name"),&VideoPlayer::get_stream_name);
|
ObjectTypeDB::bind_method(_MD("get_stream_name"),&VideoPlayer::get_stream_name);
|
||||||
|
|
||||||
ObjectTypeDB::bind_method(_MD("get_pos"),&VideoPlayer::get_pos);
|
ObjectTypeDB::bind_method(_MD("get_stream_pos"),&VideoPlayer::get_stream_pos);
|
||||||
|
|
||||||
ObjectTypeDB::bind_method(_MD("set_autoplay","enabled"),&VideoPlayer::set_autoplay);
|
ObjectTypeDB::bind_method(_MD("set_autoplay","enabled"),&VideoPlayer::set_autoplay);
|
||||||
ObjectTypeDB::bind_method(_MD("has_autoplay"),&VideoPlayer::has_autoplay);
|
ObjectTypeDB::bind_method(_MD("has_autoplay"),&VideoPlayer::has_autoplay);
|
||||||
|
|
|
@ -77,7 +77,7 @@ public:
|
||||||
float get_volume_db() const;
|
float get_volume_db() const;
|
||||||
|
|
||||||
String get_stream_name() const;
|
String get_stream_name() const;
|
||||||
float get_pos() const;
|
float get_stream_pos() const;
|
||||||
|
|
||||||
void set_autoplay(bool p_vol);
|
void set_autoplay(bool p_vol);
|
||||||
bool has_autoplay() const;
|
bool has_autoplay() const;
|
||||||
|
|
|
@ -1716,189 +1716,222 @@ void Animation::clear() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0,const TKey<TransformKey> &t1, const TKey<TransformKey> &t2, float p_alowed_linear_err,float p_alowed_angular_err,float p_max_optimizable_angle) {
|
||||||
|
|
||||||
|
|
||||||
|
real_t c = (t1.time-t0.time)/(t2.time-t0.time);
|
||||||
|
real_t t[3]={-1,-1,-1};
|
||||||
|
|
||||||
|
{ //translation
|
||||||
|
|
||||||
|
const Vector3 &v0=t0.value.loc;
|
||||||
|
const Vector3 &v1=t1.value.loc;
|
||||||
|
const Vector3 &v2=t2.value.loc;
|
||||||
|
|
||||||
|
if (v0.distance_to(v2)<CMP_EPSILON) {
|
||||||
|
//0 and 2 are close, let's see if 1 is close
|
||||||
|
if (v0.distance_to(v1)>CMP_EPSILON) {
|
||||||
|
//not close, not optimizable
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
Vector3 pd = (v2-v0);
|
||||||
|
float d0 = pd.dot(v0);
|
||||||
|
float d1 = pd.dot(v1);
|
||||||
|
float d2 = pd.dot(v2);
|
||||||
|
if (d1<d0 || d1>d2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 s[2]={ v0, v2 };
|
||||||
|
real_t d =Geometry::get_closest_point_to_segment(v1,s).distance_to(v1);
|
||||||
|
|
||||||
|
if (d>pd.length()*p_alowed_linear_err) {
|
||||||
|
return false; //beyond allowed error for colinearity
|
||||||
|
}
|
||||||
|
|
||||||
|
t[0] = (d1-d0)/(d2-d0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{ //rotation
|
||||||
|
|
||||||
|
const Quat &q0=t0.value.rot;
|
||||||
|
const Quat &q1=t1.value.rot;
|
||||||
|
const Quat &q2=t2.value.rot;
|
||||||
|
|
||||||
|
//localize both to rotation from q0
|
||||||
|
|
||||||
|
if ((q0-q2).length() < CMP_EPSILON) {
|
||||||
|
|
||||||
|
if ((q0-q1).length() > CMP_EPSILON)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
|
||||||
|
Quat r02 = (q0.inverse() * q2).normalized();
|
||||||
|
Quat r01 = (q0.inverse() * q1).normalized();
|
||||||
|
|
||||||
|
Vector3 v02,v01;
|
||||||
|
real_t a02,a01;
|
||||||
|
|
||||||
|
r02.get_axis_and_angle(v02,a02);
|
||||||
|
r01.get_axis_and_angle(v01,a01);
|
||||||
|
|
||||||
|
if (Math::abs(a02)>p_max_optimizable_angle)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (v01.dot(v02)<0) {
|
||||||
|
//make sure both rotations go the same way to compare
|
||||||
|
v02=-v02;
|
||||||
|
a02=-a02;
|
||||||
|
}
|
||||||
|
|
||||||
|
real_t err_01 = Math::acos(v01.normalized().dot(v02.normalized()))/Math_PI;
|
||||||
|
if (err_01>p_alowed_angular_err) {
|
||||||
|
//not rotating in the same axis
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a01*a02 < 0 ) {
|
||||||
|
//not rotating in the same direction
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
real_t tr = a01/a02;
|
||||||
|
if (tr<0 || tr>1)
|
||||||
|
return false; //rotating too much or too less
|
||||||
|
|
||||||
|
t[1]=tr;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
{ //scale
|
||||||
|
|
||||||
|
const Vector3 &v0=t0.value.scale;
|
||||||
|
const Vector3 &v1=t1.value.scale;
|
||||||
|
const Vector3 &v2=t2.value.scale;
|
||||||
|
|
||||||
|
if (v0.distance_to(v2)<CMP_EPSILON) {
|
||||||
|
//0 and 2 are close, let's see if 1 is close
|
||||||
|
if (v0.distance_to(v1)>CMP_EPSILON) {
|
||||||
|
//not close, not optimizable
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
Vector3 pd = (v2-v0);
|
||||||
|
float d0 = pd.dot(v0);
|
||||||
|
float d1 = pd.dot(v1);
|
||||||
|
float d2 = pd.dot(v2);
|
||||||
|
if (d1<d0 || d1>d2) {
|
||||||
|
return false; //beyond segment range
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 s[2]={ v0, v2 };
|
||||||
|
real_t d =Geometry::get_closest_point_to_segment(v1,s).distance_to(v1);
|
||||||
|
|
||||||
|
if (d>pd.length()*p_alowed_linear_err) {
|
||||||
|
return false; //beyond allowed error for colinearity
|
||||||
|
}
|
||||||
|
|
||||||
|
t[2] = (d1-d0)/(d2-d0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool erase=false;
|
||||||
|
if (t[0]==-1 && t[1]==-1 && t[2]==-1) {
|
||||||
|
|
||||||
|
erase=true;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
erase=true;
|
||||||
|
real_t lt=-1;
|
||||||
|
for(int j=0;j<3;j++) {
|
||||||
|
//search for t on first, one must be it
|
||||||
|
if (t[j]!=-1) {
|
||||||
|
lt=t[j]; //official t
|
||||||
|
//validate rest
|
||||||
|
for(int k=j+1;k<3;k++) {
|
||||||
|
if (t[k]==-1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (Math::abs(lt-t[k])>p_alowed_linear_err) {
|
||||||
|
erase=false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V( lt==-1,false );
|
||||||
|
|
||||||
|
if (erase) {
|
||||||
|
|
||||||
|
if (Math::abs(lt-c)>p_alowed_linear_err) {
|
||||||
|
//todo, evaluate changing the transition if this fails?
|
||||||
|
//this could be done as a second pass and would be
|
||||||
|
//able to optimize more
|
||||||
|
erase=false;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
//print_line(itos(i)+"because of interp");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return erase;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Animation::_transform_track_optimize(int p_idx,float p_alowed_linear_err,float p_alowed_angular_err,float p_max_optimizable_angle) {
|
void Animation::_transform_track_optimize(int p_idx,float p_alowed_linear_err,float p_alowed_angular_err,float p_max_optimizable_angle) {
|
||||||
|
|
||||||
ERR_FAIL_INDEX(p_idx,tracks.size());
|
ERR_FAIL_INDEX(p_idx,tracks.size());
|
||||||
ERR_FAIL_COND(tracks[p_idx]->type!=TYPE_TRANSFORM);
|
ERR_FAIL_COND(tracks[p_idx]->type!=TYPE_TRANSFORM);
|
||||||
TransformTrack *tt= static_cast<TransformTrack*>(tracks[p_idx]);
|
TransformTrack *tt= static_cast<TransformTrack*>(tracks[p_idx]);
|
||||||
|
bool prev_erased=false;
|
||||||
|
TKey<TransformKey> first_erased;
|
||||||
|
|
||||||
for(int i=1;i<tt->transforms.size()-1;i++) {
|
for(int i=1;i<tt->transforms.size()-1;i++) {
|
||||||
|
|
||||||
TKey<TransformKey> &t0 = tt->transforms[i-1];
|
TKey<TransformKey> &t0 = tt->transforms[i-1];
|
||||||
TKey<TransformKey> &t1 = tt->transforms[i];
|
TKey<TransformKey> &t1 = tt->transforms[i];
|
||||||
TKey<TransformKey> &t2 = tt->transforms[i+1];
|
TKey<TransformKey> &t2 = tt->transforms[i+1];
|
||||||
|
|
||||||
real_t c = (t1.time-t0.time)/(t2.time-t0.time);
|
bool erase = _transform_track_optimize_key(t0,t1,t2,p_alowed_linear_err,p_alowed_angular_err,p_max_optimizable_angle);
|
||||||
real_t t[3]={-1,-1,-1};
|
|
||||||
|
|
||||||
{ //translation
|
|
||||||
|
|
||||||
const Vector3 &v0=t0.value.loc;
|
if (prev_erased && !_transform_track_optimize_key(t0,first_erased,t2,p_alowed_linear_err,p_alowed_angular_err,p_max_optimizable_angle)) {
|
||||||
const Vector3 &v1=t1.value.loc;
|
//avoid error to go beyond first erased key
|
||||||
const Vector3 &v2=t2.value.loc;
|
erase=false;
|
||||||
|
|
||||||
if (v0.distance_to(v2)<CMP_EPSILON) {
|
|
||||||
//0 and 2 are close, let's see if 1 is close
|
|
||||||
if (v0.distance_to(v1)>CMP_EPSILON) {
|
|
||||||
//not close, not optimizable
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
Vector3 pd = (v2-v0);
|
|
||||||
float d0 = pd.dot(v0);
|
|
||||||
float d1 = pd.dot(v1);
|
|
||||||
float d2 = pd.dot(v2);
|
|
||||||
if (d1<d0 || d1>d2) {
|
|
||||||
continue; //beyond segment range
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 s[2]={ v0, v2 };
|
|
||||||
real_t d =Geometry::get_closest_point_to_segment(v1,s).distance_to(v1);
|
|
||||||
|
|
||||||
if (d>pd.length()*p_alowed_linear_err) {
|
|
||||||
continue; //beyond allowed error for colinearity
|
|
||||||
}
|
|
||||||
|
|
||||||
t[0] = (d1-d0)/(d2-d0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{ //rotation
|
|
||||||
|
|
||||||
const Quat &q0=t0.value.rot;
|
|
||||||
const Quat &q1=t1.value.rot;
|
|
||||||
const Quat &q2=t2.value.rot;
|
|
||||||
|
|
||||||
//localize both to rotation from q0
|
|
||||||
|
|
||||||
if ((q0-q2).length() < CMP_EPSILON) {
|
|
||||||
|
|
||||||
if ((q0-q1).length() > CMP_EPSILON)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
|
|
||||||
Quat r02 = (q0.inverse() * q2).normalized();
|
|
||||||
Quat r01 = (q0.inverse() * q1).normalized();
|
|
||||||
|
|
||||||
Vector3 v02,v01;
|
|
||||||
real_t a02,a01;
|
|
||||||
|
|
||||||
r02.get_axis_and_angle(v02,a02);
|
|
||||||
r01.get_axis_and_angle(v01,a01);
|
|
||||||
|
|
||||||
if (Math::abs(a02)>p_max_optimizable_angle)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (v01.dot(v02)<0) {
|
|
||||||
//make sure both rotations go the same way to compare
|
|
||||||
v02=-v02;
|
|
||||||
a02=-a02;
|
|
||||||
}
|
|
||||||
|
|
||||||
real_t err_01 = Math::acos(v01.normalized().dot(v02.normalized()))/Math_PI;
|
|
||||||
if (err_01>p_alowed_angular_err) {
|
|
||||||
//not rotating in the same axis
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (a01*a02 < 0 ) {
|
|
||||||
//not rotating in the same direction
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
real_t tr = a01/a02;
|
|
||||||
if (tr<0 || tr>1)
|
|
||||||
continue; //rotating too much or too less
|
|
||||||
|
|
||||||
t[1]=tr;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
{ //scale
|
|
||||||
|
|
||||||
const Vector3 &v0=t0.value.scale;
|
|
||||||
const Vector3 &v1=t1.value.scale;
|
|
||||||
const Vector3 &v2=t2.value.scale;
|
|
||||||
|
|
||||||
if (v0.distance_to(v2)<CMP_EPSILON) {
|
|
||||||
//0 and 2 are close, let's see if 1 is close
|
|
||||||
if (v0.distance_to(v1)>CMP_EPSILON) {
|
|
||||||
//not close, not optimizable
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
Vector3 pd = (v2-v0);
|
|
||||||
float d0 = pd.dot(v0);
|
|
||||||
float d1 = pd.dot(v1);
|
|
||||||
float d2 = pd.dot(v2);
|
|
||||||
if (d1<d0 || d1>d2) {
|
|
||||||
continue; //beyond segment range
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 s[2]={ v0, v2 };
|
|
||||||
real_t d =Geometry::get_closest_point_to_segment(v1,s).distance_to(v1);
|
|
||||||
|
|
||||||
if (d>pd.length()*p_alowed_linear_err) {
|
|
||||||
continue; //beyond allowed error for colinearity
|
|
||||||
}
|
|
||||||
|
|
||||||
t[2] = (d1-d0)/(d2-d0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool erase=false;
|
|
||||||
if (t[0]==-1 && t[1]==-1 && t[2]==-1) {
|
|
||||||
|
|
||||||
erase=true;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
erase=true;
|
|
||||||
real_t lt=-1;
|
|
||||||
for(int j=0;j<3;j++) {
|
|
||||||
//search for t on first, one must be it
|
|
||||||
if (t[j]!=-1) {
|
|
||||||
lt=t[j]; //official t
|
|
||||||
//validate rest
|
|
||||||
for(int k=j+1;k<3;k++) {
|
|
||||||
if (t[k]==-1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (Math::abs(lt-t[k])>p_alowed_linear_err) {
|
|
||||||
erase=false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ERR_CONTINUE( lt==-1 );
|
|
||||||
|
|
||||||
if (erase) {
|
|
||||||
|
|
||||||
if (Math::abs(lt-c)>p_alowed_linear_err) {
|
|
||||||
//todo, evaluate changing the transition if this fails?
|
|
||||||
//this could be done as a second pass and would be
|
|
||||||
//able to optimize more
|
|
||||||
erase=false;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
//print_line(itos(i)+"because of interp");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (erase) {
|
if (erase) {
|
||||||
|
|
||||||
|
if (!prev_erased) {
|
||||||
|
first_erased=t1;
|
||||||
|
prev_erased=true;
|
||||||
|
}
|
||||||
|
|
||||||
tt->transforms.remove(i);
|
tt->transforms.remove(i);
|
||||||
i--;
|
i--;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
prev_erased=false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -204,6 +204,7 @@ private:
|
||||||
return idxr;
|
return idxr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _transform_track_optimize_key(const TKey<TransformKey> &t0,const TKey<TransformKey> &t1, const TKey<TransformKey> &t2, float p_alowed_linear_err,float p_alowed_angular_err,float p_max_optimizable_angle);
|
||||||
void _transform_track_optimize(int p_idx, float p_allowed_err=0.05, float p_alowed_angular_err=0.01,float p_max_optimizable_angle=Math_PI*0.125);
|
void _transform_track_optimize(int p_idx, float p_allowed_err=0.05, float p_alowed_angular_err=0.01,float p_max_optimizable_angle=Math_PI*0.125);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -33,6 +33,7 @@ void VideoStream::_bind_methods() {
|
||||||
ObjectTypeDB::bind_method(_MD("get_pending_frame_count"),&VideoStream::get_pending_frame_count);
|
ObjectTypeDB::bind_method(_MD("get_pending_frame_count"),&VideoStream::get_pending_frame_count);
|
||||||
ObjectTypeDB::bind_method(_MD("pop_frame"),&VideoStream::pop_frame);
|
ObjectTypeDB::bind_method(_MD("pop_frame"),&VideoStream::pop_frame);
|
||||||
ObjectTypeDB::bind_method(_MD("peek_frame"),&VideoStream::peek_frame);
|
ObjectTypeDB::bind_method(_MD("peek_frame"),&VideoStream::peek_frame);
|
||||||
|
ObjectTypeDB::bind_method(_MD("set_audio_track","idx"),&VideoStream::set_audio_track);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,8 @@ public:
|
||||||
virtual void pop_frame(Ref<ImageTexture> p_tex)=0;
|
virtual void pop_frame(Ref<ImageTexture> p_tex)=0;
|
||||||
virtual Image peek_frame() const=0;
|
virtual Image peek_frame() const=0;
|
||||||
|
|
||||||
|
virtual void set_audio_track(int p_idx) =0;
|
||||||
|
|
||||||
virtual void update(float p_time)=0;
|
virtual void update(float p_time)=0;
|
||||||
|
|
||||||
VideoStream();
|
VideoStream();
|
||||||
|
|
|
@ -332,6 +332,7 @@ void AudioServerSW::driver_process_chunk(int p_frames,int32_t *p_buffer) {
|
||||||
void AudioServerSW::driver_process(int p_frames,int32_t *p_buffer) {
|
void AudioServerSW::driver_process(int p_frames,int32_t *p_buffer) {
|
||||||
|
|
||||||
|
|
||||||
|
_output_delay=p_frames/double(AudioDriverSW::get_singleton()->get_mix_rate());
|
||||||
//process in chunks to make sure to never process more than INTERNAL_BUFFER_SIZE
|
//process in chunks to make sure to never process more than INTERNAL_BUFFER_SIZE
|
||||||
int todo=p_frames;
|
int todo=p_frames;
|
||||||
while(todo) {
|
while(todo) {
|
||||||
|
@ -795,6 +796,8 @@ void AudioServerSW::init() {
|
||||||
mixer = memnew( AudioMixerSW( sample_manager, latency, AudioDriverSW::get_singleton()->get_mix_rate(),mix_chans,mixer_use_fx,mixer_interp,_mixer_callback,this ) );
|
mixer = memnew( AudioMixerSW( sample_manager, latency, AudioDriverSW::get_singleton()->get_mix_rate(),mix_chans,mixer_use_fx,mixer_interp,_mixer_callback,this ) );
|
||||||
mixer_step_usecs=mixer->get_step_usecs();
|
mixer_step_usecs=mixer->get_step_usecs();
|
||||||
|
|
||||||
|
_output_delay=0;
|
||||||
|
|
||||||
stream_volume=0.3;
|
stream_volume=0.3;
|
||||||
// start the audio driver
|
// start the audio driver
|
||||||
if (AudioDriverSW::get_singleton())
|
if (AudioDriverSW::get_singleton())
|
||||||
|
@ -911,6 +914,11 @@ float AudioServerSW::get_event_voice_global_volume_scale() const {
|
||||||
return event_voice_volume_scale;
|
return event_voice_volume_scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double AudioServerSW::get_output_delay() const {
|
||||||
|
|
||||||
|
return _output_delay;
|
||||||
|
}
|
||||||
|
|
||||||
double AudioServerSW::get_mix_time() const {
|
double AudioServerSW::get_mix_time() const {
|
||||||
|
|
||||||
return AudioDriverSW::get_singleton()->get_mix_time();
|
return AudioDriverSW::get_singleton()->get_mix_time();
|
||||||
|
|
|
@ -92,6 +92,8 @@ class AudioServerSW : public AudioServer {
|
||||||
float peak_left,peak_right;
|
float peak_left,peak_right;
|
||||||
uint32_t max_peak;
|
uint32_t max_peak;
|
||||||
|
|
||||||
|
double _output_delay;
|
||||||
|
|
||||||
VoiceRBSW voice_rb;
|
VoiceRBSW voice_rb;
|
||||||
|
|
||||||
bool exit_update_thread;
|
bool exit_update_thread;
|
||||||
|
@ -206,6 +208,9 @@ public:
|
||||||
|
|
||||||
virtual double get_mix_time() const; //useful for video -> audio sync
|
virtual double get_mix_time() const; //useful for video -> audio sync
|
||||||
|
|
||||||
|
virtual double get_output_delay() const;
|
||||||
|
|
||||||
|
|
||||||
AudioServerSW(SampleManagerSW *p_sample_manager);
|
AudioServerSW(SampleManagerSW *p_sample_manager);
|
||||||
~AudioServerSW();
|
~AudioServerSW();
|
||||||
|
|
||||||
|
|
|
@ -274,6 +274,7 @@ public:
|
||||||
static AudioServer *get_singleton();
|
static AudioServer *get_singleton();
|
||||||
|
|
||||||
virtual double get_mix_time() const=0; //useful for video -> audio sync
|
virtual double get_mix_time() const=0; //useful for video -> audio sync
|
||||||
|
virtual double get_output_delay() const=0;
|
||||||
|
|
||||||
AudioServer();
|
AudioServer();
|
||||||
virtual ~AudioServer();
|
virtual ~AudioServer();
|
||||||
|
|
|
@ -514,7 +514,7 @@ void Physics2DServer::_bind_methods() {
|
||||||
|
|
||||||
ObjectTypeDB::bind_method(_MD("joint_get_type","joint"),&Physics2DServer::joint_get_type);
|
ObjectTypeDB::bind_method(_MD("joint_get_type","joint"),&Physics2DServer::joint_get_type);
|
||||||
|
|
||||||
ObjectTypeDB::bind_method(_MD("free","rid"),&Physics2DServer::free);
|
ObjectTypeDB::bind_method(_MD("free_rid","rid"),&Physics2DServer::free);
|
||||||
|
|
||||||
ObjectTypeDB::bind_method(_MD("set_active","active"),&Physics2DServer::set_active);
|
ObjectTypeDB::bind_method(_MD("set_active","active"),&Physics2DServer::set_active);
|
||||||
|
|
||||||
|
|
|
@ -655,7 +655,7 @@ void PhysicsServer::_bind_methods() {
|
||||||
|
|
||||||
ObjectTypeDB::bind_method(_MD("joint_get_type","joint"),&PhysicsServer::joint_get_type);
|
ObjectTypeDB::bind_method(_MD("joint_get_type","joint"),&PhysicsServer::joint_get_type);
|
||||||
*/
|
*/
|
||||||
ObjectTypeDB::bind_method(_MD("free","rid"),&PhysicsServer::free);
|
ObjectTypeDB::bind_method(_MD("free_rid","rid"),&PhysicsServer::free);
|
||||||
|
|
||||||
ObjectTypeDB::bind_method(_MD("set_active","active"),&PhysicsServer::set_active);
|
ObjectTypeDB::bind_method(_MD("set_active","active"),&PhysicsServer::set_active);
|
||||||
|
|
||||||
|
|
|
@ -687,9 +687,7 @@ void AnimationKeyEditor::_menu_track(int p_type) {
|
||||||
|
|
||||||
case TRACK_MENU_OPTIMIZE: {
|
case TRACK_MENU_OPTIMIZE: {
|
||||||
|
|
||||||
animation->optimize();
|
optimize_dialog->popup_centered(Size2(250,180));
|
||||||
|
|
||||||
track_editor->update();
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|
||||||
|
@ -698,6 +696,18 @@ void AnimationKeyEditor::_menu_track(int p_type) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AnimationKeyEditor::_animation_optimize() {
|
||||||
|
|
||||||
|
|
||||||
|
print_line("OPTIMIZE!");
|
||||||
|
animation->optimize(optimize_linear_error->get_val(),optimize_angular_error->get_val(),optimize_max_angle->get_val());
|
||||||
|
track_editor->update();
|
||||||
|
undo_redo->clear_history();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
float AnimationKeyEditor::_get_zoom_scale() const {
|
float AnimationKeyEditor::_get_zoom_scale() const {
|
||||||
|
|
||||||
float zv = zoom->get_val();
|
float zv = zoom->get_val();
|
||||||
|
@ -2335,11 +2345,12 @@ void AnimationKeyEditor::_notification(int p_what) {
|
||||||
tpp->add_item("Out-In",TRACK_MENU_SET_ALL_TRANS_OUTIN);
|
tpp->add_item("Out-In",TRACK_MENU_SET_ALL_TRANS_OUTIN);
|
||||||
tpp->set_name("Transitions");
|
tpp->set_name("Transitions");
|
||||||
tpp->connect("item_pressed",this,"_menu_track");
|
tpp->connect("item_pressed",this,"_menu_track");
|
||||||
|
optimize_dialog->connect("confirmed",this,"_animation_optimize");
|
||||||
|
|
||||||
menu_track->get_popup()->add_child(tpp);
|
menu_track->get_popup()->add_child(tpp);
|
||||||
menu_track->get_popup()->add_submenu_item("Set Transitions..","Transitions");
|
menu_track->get_popup()->add_submenu_item("Set Transitions..","Transitions");
|
||||||
//menu_track->get_popup()->add_separator();
|
menu_track->get_popup()->add_separator();
|
||||||
//menu_track->get_popup()->add_item("Optimize Animation",TRACK_MENU_OPTIMIZE);
|
menu_track->get_popup()->add_item("Optimize Animation",TRACK_MENU_OPTIMIZE);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -3099,6 +3110,7 @@ void AnimationKeyEditor::_bind_methods() {
|
||||||
ObjectTypeDB::bind_method(_MD("_animation_len_update"),&AnimationKeyEditor::_animation_len_update);
|
ObjectTypeDB::bind_method(_MD("_animation_len_update"),&AnimationKeyEditor::_animation_len_update);
|
||||||
|
|
||||||
ObjectTypeDB::bind_method(_MD("set_animation"),&AnimationKeyEditor::set_animation);
|
ObjectTypeDB::bind_method(_MD("set_animation"),&AnimationKeyEditor::set_animation);
|
||||||
|
ObjectTypeDB::bind_method(_MD("_animation_optimize"),&AnimationKeyEditor::_animation_optimize);
|
||||||
|
|
||||||
|
|
||||||
ADD_SIGNAL( MethodInfo("resource_selected", PropertyInfo( Variant::OBJECT, "res"),PropertyInfo( Variant::STRING, "prop") ) );
|
ADD_SIGNAL( MethodInfo("resource_selected", PropertyInfo( Variant::OBJECT, "res"),PropertyInfo( Variant::STRING, "prop") ) );
|
||||||
|
@ -3224,6 +3236,37 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h
|
||||||
remove_button->set_disabled(true);
|
remove_button->set_disabled(true);
|
||||||
remove_button->set_tooltip("Remove selected track.");
|
remove_button->set_tooltip("Remove selected track.");
|
||||||
|
|
||||||
|
|
||||||
|
optimize_dialog = memnew( ConfirmationDialog );
|
||||||
|
add_child(optimize_dialog);
|
||||||
|
optimize_dialog->set_title("Anim. Optimizer");
|
||||||
|
VBoxContainer *optimize_vb = memnew( VBoxContainer );
|
||||||
|
optimize_dialog->add_child(optimize_vb);
|
||||||
|
optimize_dialog->set_child_rect(optimize_vb);
|
||||||
|
optimize_linear_error = memnew( SpinBox );
|
||||||
|
optimize_linear_error->set_max(1.0);
|
||||||
|
optimize_linear_error->set_min(0.001);
|
||||||
|
optimize_linear_error->set_step(0.001);
|
||||||
|
optimize_linear_error->set_val(0.05);
|
||||||
|
optimize_vb->add_margin_child("Max. Linear Error:",optimize_linear_error);
|
||||||
|
optimize_angular_error = memnew( SpinBox );
|
||||||
|
optimize_angular_error->set_max(1.0);
|
||||||
|
optimize_angular_error->set_min(0.001);
|
||||||
|
optimize_angular_error->set_step(0.001);
|
||||||
|
optimize_angular_error->set_val(0.01);
|
||||||
|
|
||||||
|
optimize_vb->add_margin_child("Max. Angular Error:",optimize_angular_error);
|
||||||
|
optimize_max_angle = memnew( SpinBox );
|
||||||
|
optimize_vb->add_margin_child("Max Optimizable Angle:",optimize_max_angle);
|
||||||
|
optimize_max_angle->set_max(360.0);
|
||||||
|
optimize_max_angle->set_min(0.0);
|
||||||
|
optimize_max_angle->set_step(0.1);
|
||||||
|
optimize_max_angle->set_val(22);
|
||||||
|
|
||||||
|
optimize_dialog->get_ok()->set_text("Optimize");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*keying = memnew( Button );
|
/*keying = memnew( Button );
|
||||||
keying->set_toggle_mode(true);
|
keying->set_toggle_mode(true);
|
||||||
//keying->set_text("Keys");
|
//keying->set_text("Keys");
|
||||||
|
|
|
@ -169,6 +169,11 @@ class AnimationKeyEditor : public VBoxContainer {
|
||||||
ToolButton *move_down_button;
|
ToolButton *move_down_button;
|
||||||
ToolButton *remove_button;
|
ToolButton *remove_button;
|
||||||
|
|
||||||
|
ConfirmationDialog *optimize_dialog;
|
||||||
|
SpinBox *optimize_linear_error;
|
||||||
|
SpinBox *optimize_angular_error;
|
||||||
|
SpinBox *optimize_max_angle;
|
||||||
|
|
||||||
SpinBox *step;
|
SpinBox *step;
|
||||||
|
|
||||||
MenuButton *menu_track;
|
MenuButton *menu_track;
|
||||||
|
@ -257,6 +262,7 @@ class AnimationKeyEditor : public VBoxContainer {
|
||||||
StringName alc;
|
StringName alc;
|
||||||
|
|
||||||
void _animation_changed();
|
void _animation_changed();
|
||||||
|
void _animation_optimize();
|
||||||
|
|
||||||
void _scroll_changed(double);
|
void _scroll_changed(double);
|
||||||
|
|
||||||
|
|
|
@ -992,6 +992,35 @@ void EditorFileSystem::_resource_saved(const String& p_path){
|
||||||
EditorFileSystem::get_singleton()->update_file(p_path);
|
EditorFileSystem::get_singleton()->update_file(p_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String EditorFileSystem::_find_first_from_source(EditorFileSystemDirectory* p_dir,const String &p_src) const {
|
||||||
|
|
||||||
|
for(int i=0;i<p_dir->files.size();i++) {
|
||||||
|
for(int j=0;j<p_dir->files[i].meta.sources.size();j++) {
|
||||||
|
|
||||||
|
if (p_dir->files[i].meta.sources[j].path==p_src)
|
||||||
|
return p_dir->get_file_path(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=0;i<p_dir->subdirs.size();i++) {
|
||||||
|
|
||||||
|
String ret = _find_first_from_source(p_dir->subdirs[i],p_src);
|
||||||
|
if (ret.length()>0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return String();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String EditorFileSystem::find_resource_from_source(const String& p_path) const {
|
||||||
|
|
||||||
|
|
||||||
|
if (filesystem)
|
||||||
|
return _find_first_from_source(filesystem,p_path);
|
||||||
|
return String();
|
||||||
|
}
|
||||||
|
|
||||||
void EditorFileSystem::update_file(const String& p_file) {
|
void EditorFileSystem::update_file(const String& p_file) {
|
||||||
|
|
||||||
EditorFileSystemDirectory *fs=NULL;
|
EditorFileSystemDirectory *fs=NULL;
|
||||||
|
|
|
@ -75,6 +75,7 @@ class EditorFileSystemDirectory : public Object {
|
||||||
|
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
|
|
||||||
friend class EditorFileSystem;
|
friend class EditorFileSystem;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -180,6 +181,7 @@ class EditorFileSystem : public Node {
|
||||||
List<String> sources_changed;
|
List<String> sources_changed;
|
||||||
|
|
||||||
static void _resource_saved(const String& p_path);
|
static void _resource_saved(const String& p_path);
|
||||||
|
String _find_first_from_source(EditorFileSystemDirectory* p_dir,const String &p_src) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -197,6 +199,7 @@ public:
|
||||||
void scan_sources();
|
void scan_sources();
|
||||||
void get_changed_sources(List<String> *r_changed);
|
void get_changed_sources(List<String> *r_changed);
|
||||||
void update_file(const String& p_file);
|
void update_file(const String& p_file);
|
||||||
|
String find_resource_from_source(const String& p_path) const;
|
||||||
EditorFileSystemDirectory *get_path(const String& p_path);
|
EditorFileSystemDirectory *get_path(const String& p_path);
|
||||||
String get_file_type(const String& p_file) const;
|
String get_file_type(const String& p_file) const;
|
||||||
EditorFileSystem();
|
EditorFileSystem();
|
||||||
|
|
|
@ -1844,12 +1844,15 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones
|
||||||
anim_length=collada.state.animation_clips[p_clip].end;
|
anim_length=collada.state.animation_clips[p_clip].end;
|
||||||
|
|
||||||
while(f<anim_length) {
|
while(f<anim_length) {
|
||||||
if (f>=anim_length)
|
|
||||||
f=anim_length;
|
|
||||||
|
|
||||||
base_snapshots.push_back(f);
|
base_snapshots.push_back(f);
|
||||||
f+=snapshot_interval;
|
f+=snapshot_interval;
|
||||||
|
|
||||||
|
if (f>=anim_length) {
|
||||||
|
base_snapshots.push_back(anim_length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//print_line("anim len: "+rtos(anim_length));
|
//print_line("anim len: "+rtos(anim_length));
|
||||||
animation->set_length(anim_length);
|
animation->set_length(anim_length);
|
||||||
|
|
||||||
|
@ -1894,6 +1897,8 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones
|
||||||
for(int i=0;i<at.keys.size();i++)
|
for(int i=0;i<at.keys.size();i++)
|
||||||
snapshots.push_back(at.keys[i].time);
|
snapshots.push_back(at.keys[i].time);
|
||||||
|
|
||||||
|
print_line("using anim snapshots");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2185,8 +2190,6 @@ Node* EditorSceneImporterCollada::import_scene(const String& p_path, uint32_t p_
|
||||||
else
|
else
|
||||||
name=state.animations[i]->get_name();
|
name=state.animations[i]->get_name();
|
||||||
|
|
||||||
if (p_flags&IMPORT_ANIMATION_OPTIMIZE)
|
|
||||||
state.animations[i]->optimize();
|
|
||||||
if (p_flags&IMPORT_ANIMATION_DETECT_LOOP) {
|
if (p_flags&IMPORT_ANIMATION_DETECT_LOOP) {
|
||||||
|
|
||||||
if (name.begins_with("loop") || name.ends_with("loop") || name.begins_with("cycle") || name.ends_with("cycle")) {
|
if (name.begins_with("loop") || name.ends_with("loop") || name.begins_with("cycle") || name.ends_with("cycle")) {
|
||||||
|
@ -2232,8 +2235,6 @@ Ref<Animation> EditorSceneImporterCollada::import_animation(const String& p_path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_flags&IMPORT_ANIMATION_OPTIMIZE)
|
|
||||||
anim->optimize();
|
|
||||||
|
|
||||||
return anim;
|
return anim;
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,17 +80,25 @@ class EditorImportAnimationOptions : public VBoxContainer {
|
||||||
|
|
||||||
|
|
||||||
TreeItem *fps;
|
TreeItem *fps;
|
||||||
|
TreeItem* optimize_linear_error;
|
||||||
|
TreeItem* optimize_angular_error;
|
||||||
|
TreeItem* optimize_max_angle;
|
||||||
|
|
||||||
TreeItem *clips_base;
|
TreeItem *clips_base;
|
||||||
|
|
||||||
TextEdit *filters;
|
TextEdit *filters;
|
||||||
Vector<TreeItem*> clips;
|
Vector<TreeItem*> clips;
|
||||||
|
|
||||||
Tree *flags;
|
Tree *flags;
|
||||||
Tree *clips_tree;
|
Tree *clips_tree;
|
||||||
|
Tree *optimization_tree;
|
||||||
Vector<TreeItem*> items;
|
Vector<TreeItem*> items;
|
||||||
|
|
||||||
bool updating;
|
bool updating;
|
||||||
bool validating;
|
bool validating;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void _changed();
|
void _changed();
|
||||||
void _item_edited();
|
void _item_edited();
|
||||||
void _button_action(Object *p_obj,int p_col,int p_id);
|
void _button_action(Object *p_obj,int p_col,int p_id);
|
||||||
|
@ -107,6 +115,15 @@ public:
|
||||||
void set_fps(int p_fps);
|
void set_fps(int p_fps);
|
||||||
int get_fps() const;
|
int get_fps() const;
|
||||||
|
|
||||||
|
void set_optimize_linear_error(float p_error);
|
||||||
|
float get_optimize_linear_error() const;
|
||||||
|
|
||||||
|
void set_optimize_angular_error(float p_error);
|
||||||
|
float get_optimize_angular_error() const;
|
||||||
|
|
||||||
|
void set_optimize_max_angle(float p_error);
|
||||||
|
float get_optimize_max_angle() const;
|
||||||
|
|
||||||
void setup_clips(const Array& p_clips);
|
void setup_clips(const Array& p_clips);
|
||||||
Array get_clips() const;
|
Array get_clips() const;
|
||||||
|
|
||||||
|
@ -453,9 +470,41 @@ EditorImportAnimationOptions::EditorImportAnimationOptions() {
|
||||||
fps = flags->create_item(fps_base);
|
fps = flags->create_item(fps_base);
|
||||||
fps->set_cell_mode(0,TreeItem::CELL_MODE_RANGE);
|
fps->set_cell_mode(0,TreeItem::CELL_MODE_RANGE);
|
||||||
fps->set_editable(0,true);
|
fps->set_editable(0,true);
|
||||||
fps->set_range(0,15);
|
|
||||||
fps->set_range_config(0,1,120,1);
|
fps->set_range_config(0,1,120,1);
|
||||||
|
fps->set_range(0,15);
|
||||||
|
|
||||||
|
optimization_tree = memnew( Tree );
|
||||||
|
optimization_tree->set_columns(2);
|
||||||
|
tab->add_child(optimization_tree);
|
||||||
|
optimization_tree->set_name("Optimizer");
|
||||||
|
optimization_tree->set_column_expand(0,true);
|
||||||
|
optimization_tree->set_column_expand(1,false);
|
||||||
|
optimization_tree->set_column_min_width(1,80);
|
||||||
|
optimization_tree->set_hide_root(true);
|
||||||
|
|
||||||
|
|
||||||
|
TreeItem *optimize_root = optimization_tree->create_item();
|
||||||
|
|
||||||
|
optimize_linear_error = optimization_tree->create_item(optimize_root);
|
||||||
|
optimize_linear_error->set_text(0,"Max Linear Error");
|
||||||
|
optimize_linear_error->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
|
||||||
|
optimize_linear_error->set_editable(1,true);
|
||||||
|
optimize_linear_error->set_range_config(1,0,1,0.001);
|
||||||
|
optimize_linear_error->set_range(1,0.05);
|
||||||
|
|
||||||
|
optimize_angular_error = optimization_tree->create_item(optimize_root);
|
||||||
|
optimize_angular_error->set_text(0,"Max Angular Error");
|
||||||
|
optimize_angular_error->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
|
||||||
|
optimize_angular_error->set_editable(1,true);
|
||||||
|
optimize_angular_error->set_range_config(1,0,1,0.001);
|
||||||
|
optimize_angular_error->set_range(1,0.01);
|
||||||
|
|
||||||
|
optimize_max_angle = optimization_tree->create_item(optimize_root);
|
||||||
|
optimize_max_angle->set_text(0,"Max Angle");
|
||||||
|
optimize_max_angle->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
|
||||||
|
optimize_max_angle->set_editable(1,true);
|
||||||
|
optimize_max_angle->set_range_config(1,0,360,0.001);
|
||||||
|
optimize_max_angle->set_range(1,int(180*0.125));
|
||||||
|
|
||||||
clips_tree = memnew( Tree );
|
clips_tree = memnew( Tree );
|
||||||
clips_tree->set_hide_root(true);
|
clips_tree->set_hide_root(true);
|
||||||
|
@ -498,6 +547,38 @@ int EditorImportAnimationOptions::get_fps() const {
|
||||||
return fps->get_range(0);
|
return fps->get_range(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EditorImportAnimationOptions::set_optimize_linear_error(float p_optimize_linear_error) {
|
||||||
|
|
||||||
|
optimize_linear_error->set_range(1,p_optimize_linear_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
float EditorImportAnimationOptions::get_optimize_linear_error() const {
|
||||||
|
|
||||||
|
return optimize_linear_error->get_range(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorImportAnimationOptions::set_optimize_angular_error(float p_optimize_angular_error) {
|
||||||
|
|
||||||
|
optimize_angular_error->set_range(1,p_optimize_angular_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
float EditorImportAnimationOptions::get_optimize_angular_error() const {
|
||||||
|
|
||||||
|
return optimize_angular_error->get_range(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorImportAnimationOptions::set_optimize_max_angle(float p_optimize_max_angle) {
|
||||||
|
|
||||||
|
optimize_max_angle->set_range(1,p_optimize_max_angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
float EditorImportAnimationOptions::get_optimize_max_angle() const {
|
||||||
|
|
||||||
|
return optimize_max_angle->get_range(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void EditorImportAnimationOptions::set_filter(const String& p_filter) {
|
void EditorImportAnimationOptions::set_filter(const String& p_filter) {
|
||||||
|
|
||||||
filters->set_text(p_filter);
|
filters->set_text(p_filter);
|
||||||
|
@ -544,6 +625,17 @@ void EditorSceneImportDialog::_choose_file(const String& p_path) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (p_path!=String()) {
|
||||||
|
|
||||||
|
String from_path = EditorFileSystem::get_singleton()->find_resource_from_source(EditorImportPlugin::validate_source_path(p_path));
|
||||||
|
print_line("from path.."+from_path);
|
||||||
|
if (from_path!=String()) {
|
||||||
|
popup_import(from_path);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
import_path->set_text(p_path);
|
import_path->set_text(p_path);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -650,6 +742,9 @@ void EditorSceneImportDialog::_import(bool p_and_open) {
|
||||||
rim->set_option("texture_quality",texture_options->get_quality());
|
rim->set_option("texture_quality",texture_options->get_quality());
|
||||||
rim->set_option("animation_flags",animation_options->get_flags());
|
rim->set_option("animation_flags",animation_options->get_flags());
|
||||||
rim->set_option("animation_bake_fps",animation_options->get_fps());
|
rim->set_option("animation_bake_fps",animation_options->get_fps());
|
||||||
|
rim->set_option("animation_optimizer_linear_error",animation_options->get_optimize_linear_error());
|
||||||
|
rim->set_option("animation_optimizer_angular_error",animation_options->get_optimize_angular_error());
|
||||||
|
rim->set_option("animation_optimizer_max_angle",animation_options->get_optimize_max_angle());
|
||||||
rim->set_option("animation_filters",animation_options->get_filter());
|
rim->set_option("animation_filters",animation_options->get_filter());
|
||||||
rim->set_option("animation_clips",animation_options->get_clips());
|
rim->set_option("animation_clips",animation_options->get_clips());
|
||||||
rim->set_option("post_import_script",script_path->get_text()!=String()?EditorImportPlugin::validate_source_path(script_path->get_text()):String());
|
rim->set_option("post_import_script",script_path->get_text()!=String()?EditorImportPlugin::validate_source_path(script_path->get_text()):String());
|
||||||
|
@ -791,6 +886,13 @@ void EditorSceneImportDialog::popup_import(const String &p_from) {
|
||||||
animation_options->set_filter(rimd->get_option("animation_filters"));
|
animation_options->set_filter(rimd->get_option("animation_filters"));
|
||||||
if (rimd->has_option("animation_bake_fps"))
|
if (rimd->has_option("animation_bake_fps"))
|
||||||
animation_options->set_fps(rimd->get_option("animation_bake_fps"));
|
animation_options->set_fps(rimd->get_option("animation_bake_fps"));
|
||||||
|
if (rimd->has_option("animation_optimizer_linear_error"))
|
||||||
|
animation_options->set_optimize_linear_error(rimd->get_option("animation_optimizer_linear_error"));
|
||||||
|
if (rimd->has_option("animation_optimizer_angular_error"))
|
||||||
|
animation_options->set_optimize_angular_error(rimd->get_option("animation_optimizer_angular_error"));
|
||||||
|
if (rimd->has_option("animation_optimizer_max_angle"))
|
||||||
|
animation_options->set_optimize_max_angle(rimd->get_option("animation_optimizer_max_angle"));
|
||||||
|
|
||||||
script_path->set_text(rimd->get_option("post_import_script"));
|
script_path->set_text(rimd->get_option("post_import_script"));
|
||||||
if (rimd->has_option("import_this_time"))
|
if (rimd->has_option("import_this_time"))
|
||||||
this_import->select(rimd->get_option("import_this_time"));
|
this_import->select(rimd->get_option("import_this_time"));
|
||||||
|
@ -2223,6 +2325,8 @@ Error EditorSceneImportPlugin::import1(const Ref<ResourceImportMetadata>& p_from
|
||||||
int fps = 24;
|
int fps = 24;
|
||||||
if (from->has_option("animation_bake_fps"))
|
if (from->has_option("animation_bake_fps"))
|
||||||
fps=from->get_option("animation_bake_fps");
|
fps=from->get_option("animation_bake_fps");
|
||||||
|
|
||||||
|
|
||||||
Array clips;
|
Array clips;
|
||||||
if (from->has_option("animation_clips"))
|
if (from->has_option("animation_clips"))
|
||||||
clips=from->get_option("animation_clips");
|
clips=from->get_option("animation_clips");
|
||||||
|
@ -2503,6 +2607,26 @@ void EditorSceneImportPlugin::_filter_tracks(Node *scene, const String& p_text)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditorSceneImportPlugin::_optimize_animations(Node *scene, float p_max_lin_error,float p_max_ang_error,float p_max_angle) {
|
||||||
|
|
||||||
|
if (!scene->has_node(String("AnimationPlayer")))
|
||||||
|
return;
|
||||||
|
Node* n = scene->get_node(String("AnimationPlayer"));
|
||||||
|
ERR_FAIL_COND(!n);
|
||||||
|
AnimationPlayer *anim = n->cast_to<AnimationPlayer>();
|
||||||
|
ERR_FAIL_COND(!anim);
|
||||||
|
|
||||||
|
|
||||||
|
List<StringName> anim_names;
|
||||||
|
anim->get_animation_list(&anim_names);
|
||||||
|
for(List<StringName>::Element *E=anim_names.front();E;E=E->next()) {
|
||||||
|
|
||||||
|
Ref<Animation> a = anim->get_animation(E->get());
|
||||||
|
a->optimize(p_max_lin_error,p_max_ang_error,Math::deg2rad(p_max_angle));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, const Ref<ResourceImportMetadata>& p_from) {
|
Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, const Ref<ResourceImportMetadata>& p_from) {
|
||||||
|
|
||||||
Error err=OK;
|
Error err=OK;
|
||||||
|
@ -2512,6 +2636,16 @@ Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, c
|
||||||
Array animation_clips = p_from->get_option("animation_clips");
|
Array animation_clips = p_from->get_option("animation_clips");
|
||||||
String animation_filter = p_from->get_option("animation_filters");
|
String animation_filter = p_from->get_option("animation_filters");
|
||||||
int scene_flags = from->get_option("flags");
|
int scene_flags = from->get_option("flags");
|
||||||
|
float anim_optimizer_linerr=0.05;
|
||||||
|
float anim_optimizer_angerr=0.01;
|
||||||
|
float anim_optimizer_maxang=22;
|
||||||
|
|
||||||
|
if (from->has_option("animation_optimizer_linear_error"))
|
||||||
|
anim_optimizer_linerr=from->get_option("animation_optimizer_linear_error");
|
||||||
|
if (from->has_option("animation_optimizer_angular_error"))
|
||||||
|
anim_optimizer_angerr=from->get_option("animation_optimizer_angular_error");
|
||||||
|
if (from->has_option("animation_optimizer_max_angle"))
|
||||||
|
anim_optimizer_maxang=from->get_option("animation_optimizer_max_angle");
|
||||||
|
|
||||||
EditorProgress progress("import","Import Scene",104);
|
EditorProgress progress("import","Import Scene",104);
|
||||||
progress.step("Importing Scene..",2);
|
progress.step("Importing Scene..",2);
|
||||||
|
@ -2536,6 +2670,8 @@ Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, c
|
||||||
Map< Ref<ImageTexture>,TextureRole > imagemap;
|
Map< Ref<ImageTexture>,TextureRole > imagemap;
|
||||||
|
|
||||||
scene=_fix_node(scene,scene,collision_map,scene_flags,imagemap);
|
scene=_fix_node(scene,scene,collision_map,scene_flags,imagemap);
|
||||||
|
if (animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_OPTIMIZE)
|
||||||
|
_optimize_animations(scene,anim_optimizer_linerr,anim_optimizer_angerr,anim_optimizer_maxang);
|
||||||
if (animation_clips.size())
|
if (animation_clips.size())
|
||||||
_create_clips(scene,animation_clips,animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS);
|
_create_clips(scene,animation_clips,animation_flags&EditorSceneAnimationImportPlugin::ANIMATION_FORCE_ALL_TRACKS_IN_ALL_CLIPS);
|
||||||
|
|
||||||
|
|
|
@ -114,6 +114,7 @@ class EditorSceneImportPlugin : public EditorImportPlugin {
|
||||||
void _merge_existing_node(Node *p_node,Node *p_imported_scene,Set<Ref<Resource> >& checked_resources,Set<Node*> &checked_nodes);
|
void _merge_existing_node(Node *p_node,Node *p_imported_scene,Set<Ref<Resource> >& checked_resources,Set<Node*> &checked_nodes);
|
||||||
|
|
||||||
void _add_new_nodes(Node *p_node,Node *p_imported,Node *p_imported_scene,Set<Node*> &checked_nodes);
|
void _add_new_nodes(Node *p_node,Node *p_imported,Node *p_imported_scene,Set<Node*> &checked_nodes);
|
||||||
|
void _optimize_animations(Node *scene, float p_max_lin_error,float p_max_ang_error,float p_max_angle);
|
||||||
|
|
||||||
void _merge_scenes(Node *p_node, Node *p_imported);
|
void _merge_scenes(Node *p_node, Node *p_imported);
|
||||||
void _scan_materials(Node*p_base,Node *p_node,Map<String,Ref<Material> > &mesh_materials,Map<String,Ref<Material> >& override_materials);
|
void _scan_materials(Node*p_base,Node *p_node,Map<String,Ref<Material> > &mesh_materials,Map<String,Ref<Material> >& override_materials);
|
||||||
|
|
|
@ -1457,7 +1457,7 @@ class DaeExporter:
|
||||||
|
|
||||||
print(str(x))
|
print(str(x))
|
||||||
|
|
||||||
tcn = self.export_animation(int(x.frame_range[0]),int(x.frame_range[1]),allowed_skeletons)
|
tcn = self.export_animation(int(x.frame_range[0]),int(x.frame_range[1]+0.5),allowed_skeletons)
|
||||||
framelen=(1.0/self.scene.render.fps)
|
framelen=(1.0/self.scene.render.fps)
|
||||||
start = x.frame_range[0]*framelen
|
start = x.frame_range[0]*framelen
|
||||||
end = x.frame_range[1]*framelen
|
end = x.frame_range[1]*framelen
|
||||||
|
|
Loading…
Reference in New Issue