diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index 513c7a94709..f50330447ca 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -577,9 +577,9 @@ float _OS::get_frames_per_second() const { return OS::get_singleton()->get_frames_per_second(); } -Error _OS::native_video_play(String p_path, float p_volume) { +Error _OS::native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track) { - return OS::get_singleton()->native_video_play(p_path, p_volume); + return OS::get_singleton()->native_video_play(p_path, p_volume, p_audio_track, p_subtitle_track); }; bool _OS::native_video_is_playing() { diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index b3040a96cab..101dc1ab949 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -108,7 +108,7 @@ public: bool is_video_mode_resizable(int p_screen=0) const; Array get_fullscreen_mode_list(int p_screen=0) const; - Error native_video_play(String p_path, float p_volume); + Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track); bool native_video_is_playing(); void native_video_pause(); void native_video_stop(); diff --git a/core/os/os.cpp b/core/os/os.cpp index 53ca7c3a49c..e56f4a49043 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -438,7 +438,7 @@ int OS::get_processor_count() const { return 1; } -Error OS::native_video_play(String p_path, float p_volume) { +Error OS::native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track) { return FAILED; }; diff --git a/core/os/os.h b/core/os/os.h index ed7e1e4324b..5e084f63735 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -323,7 +323,7 @@ public: virtual String get_unique_ID() const; - virtual Error native_video_play(String p_path, float p_volume); + virtual Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track); virtual bool native_video_is_playing() const; virtual void native_video_pause(); virtual void native_video_stop(); diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py index c25742a8542..acab6fe546f 100644 --- a/platform/iphone/detect.py +++ b/platform/iphone/detect.py @@ -21,7 +21,8 @@ def get_opts(): return [ ('IPHONEPLATFORM', 'name of the iphone platform', 'iPhoneOS'), ('IPHONEPATH', 'the path to iphone toolchain', '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain'), - ('IOS_SDK_VERSION', 'The SDK version', 'iPhoneOS7.0'), + #('IOS_SDK_VERSION', 'The SDK version', 'iPhoneOS7.0'), + ('IOS_SDK_VERSION', 'The SDK version', 'iPhoneOS8.1'), ('IPHONESDK', 'path to the iphone SDK', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/${IOS_SDK_VERSION}.sdk/'), ('game_center', 'Support for game center', 'yes'), ('store_kit', 'Support for in-app store', 'yes'), @@ -79,6 +80,7 @@ def configure(env): '-framework', 'Security', #'-framework', 'AdSupport', '-framework', 'MediaPlayer', + '-framework', 'AVFoundation', ]) if env['game_center'] == 'yes': diff --git a/platform/iphone/gl_view.h b/platform/iphone/gl_view.h index 3e6181ab90c..8ae7c2f87db 100755 --- a/platform/iphone/gl_view.h +++ b/platform/iphone/gl_view.h @@ -32,6 +32,7 @@ #import #import #import +#import @protocol GLViewDelegate; @@ -66,6 +67,13 @@ @property(nonatomic, assign) id delegate; +// AVPlayer-related properties +@property(strong, nonatomic) AVAsset *avAsset; +@property(strong, nonatomic) AVPlayerItem *avPlayerItem; +@property(strong, nonatomic) AVPlayer *avPlayer; +@property(strong, nonatomic) AVPlayerLayer *avPlayerLayer; + +// Old videoplayer properties @property(strong, nonatomic) MPMoviePlayerController *moviePlayerController; @property(strong, nonatomic) UIWindow *backgroundWindow; diff --git a/platform/iphone/gl_view.mm b/platform/iphone/gl_view.mm index 06b679c3056..a25e740883f 100755 --- a/platform/iphone/gl_view.mm +++ b/platform/iphone/gl_view.mm @@ -65,6 +65,7 @@ void _hide_keyboard() { keyboard_text = ""; }; +/* bool _play_video(String p_path, float p_volume) { float player_volume = p_volume * AudioServer::get_singleton()->get_singleton()->get_stream_global_volume_scale(); @@ -96,24 +97,87 @@ bool _play_video(String p_path, float p_volume) { return true; } +*/ + +bool _play_video(String p_path, float p_volume, String p_audio_track, String p_subtitle_track) { + p_path = Globals::get_singleton()->globalize_path(p_path); + + NSString* file_path = [[[NSString alloc] initWithUTF8String:p_path.utf8().get_data()] autorelease]; + //NSURL *file_url = [NSURL fileURLWithPath:file_path]; + + _instance.avAsset = [AVAsset assetWithURL:[NSURL fileURLWithPath:file_path]]; + _instance.avPlayerItem =[[AVPlayerItem alloc]initWithAsset:_instance.avAsset]; + _instance.avPlayer = [[AVPlayer alloc]initWithPlayerItem:_instance.avPlayerItem]; + _instance.avPlayerLayer =[AVPlayerLayer playerLayerWithPlayer:_instance.avPlayer]; + + [_instance.avPlayer addObserver:_instance forKeyPath:@"status" options:0 context:nil]; + [[NSNotificationCenter defaultCenter] addObserver:_instance + selector:@selector(playerItemDidReachEnd:) + name:AVPlayerItemDidPlayToEndTimeNotification + object:[_instance.avPlayer currentItem]]; + + [_instance.avPlayerLayer setFrame:_instance.bounds]; + [_instance.layer addSublayer:_instance.avPlayerLayer]; + [_instance.avPlayer play]; + + AVMediaSelectionGroup *audioGroup = [_instance.avAsset mediaSelectionGroupForMediaCharacteristic: AVMediaCharacteristicAudible]; + + for (id track in audioGroup.options) + { + NSString* language = [[track locale] localeIdentifier]; + NSLog(@"subtitle lang: %@", language); + + if ([language isEqualToString:[NSString stringWithUTF8String:p_audio_track.utf8()]]) + { + [_instance.avPlayer.currentItem selectMediaOption:track inMediaSelectionGroup: audioGroup]; + break; + } + } + + AVMediaSelectionGroup *subtitlesGroup = [_instance.avAsset mediaSelectionGroupForMediaCharacteristic: AVMediaCharacteristicLegible]; + NSArray *useableTracks = [AVMediaSelectionGroup mediaSelectionOptionsFromArray:subtitlesGroup.options withoutMediaCharacteristics:[NSArray arrayWithObject:AVMediaCharacteristicContainsOnlyForcedSubtitles]]; + + for (id track in useableTracks) + { + NSString* language = [[track locale] localeIdentifier]; + NSLog(@"subtitle lang: %@", language); + + if ([language isEqualToString:[NSString stringWithUTF8String:p_subtitle_track.utf8()]]) + { + [_instance.avPlayer.currentItem selectMediaOption:track inMediaSelectionGroup: subtitlesGroup]; + break; + } + } + + video_playing = true; + + return true; +} bool _is_video_playing() { //NSInteger playback_state = _instance.moviePlayerController.playbackState; - return video_playing || _instance.moviePlayerController.playbackState == MPMoviePlaybackStatePlaying; + //return video_playing || _instance.moviePlayerController.playbackState == MPMoviePlaybackStatePlaying; //if (video_found_error) // return false; //return (_instance.moviePlayerController.playbackState == MPMoviePlaybackStatePlaying); + + return video_playing || (_instance.avPlayer.rate > 0 && !_instance.avPlayer.error); } void _pause_video() { - [_instance.moviePlayerController pause]; + //[_instance.moviePlayerController pause]; + [_instance.avPlayer pause]; video_playing = false; } void _stop_video() { - [_instance.moviePlayerController stop]; - [_instance.moviePlayerController.view removeFromSuperview]; + //[_instance.moviePlayerController stop]; + //[_instance.moviePlayerController.view removeFromSuperview]; //[[MPMusicPlayerController applicationMusicPlayer] setVolume: video_previous_volume]; + + [_instance.avPlayer pause]; + [_instance.avPlayerLayer removeFromSuperlayer]; + _instance.avPlayer = nil; video_playing = false; } @@ -523,6 +587,21 @@ static void clear_touches() { [super dealloc]; } +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object + change:(NSDictionary *)change context:(void *)context { + if (object == _instance.avPlayer && [keyPath isEqualToString:@"status"]) { + if (_instance.avPlayer.status == AVPlayerStatusFailed) { + _stop_video(); + video_found_error = true; + } + } +} + +- (void)playerItemDidReachEnd:(NSNotification *)notification { + _stop_video(); +} + +/* - (void)moviePlayBackDidFinish:(NSNotification*)notification { @@ -557,5 +636,6 @@ static void clear_touches() { //[[MPMusicPlayerController applicationMusicPlayer] setVolume: video_previous_volume]; video_playing = false; } +*/ @end diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp index 2ef732183b2..dee018473af 100644 --- a/platform/iphone/os_iphone.cpp +++ b/platform/iphone/os_iphone.cpp @@ -485,13 +485,13 @@ String OSIPhone::get_locale() const { return locale_code; } -extern bool _play_video(String p_path, float p_volume); +extern bool _play_video(String p_path, float p_volume, String p_audio_track, String p_subtitle_track); extern bool _is_video_playing(); extern void _pause_video(); extern void _stop_video(); -Error OSIPhone::native_video_play(String p_path, float p_volume) { - if ( _play_video(p_path, p_volume) ) +Error OSIPhone::native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track) { + if ( _play_video(p_path, p_volume, p_audio_track, p_subtitle_track) ) return OK; return FAILED; } diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h index 14b46816e93..7fb306ea130 100644 --- a/platform/iphone/os_iphone.h +++ b/platform/iphone/os_iphone.h @@ -184,7 +184,7 @@ public: void set_unique_ID(String p_ID); String get_unique_ID() const; - virtual Error native_video_play(String p_path, float p_volume); + virtual Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track); virtual bool native_video_is_playing() const; virtual void native_video_pause(); virtual void native_video_stop(); diff --git a/platform/windows/packet_peer_udp_winsock.cpp b/platform/windows/packet_peer_udp_winsock.cpp index c28d72c99c1..aff92b8fc8b 100644 --- a/platform/windows/packet_peer_udp_winsock.cpp +++ b/platform/windows/packet_peer_udp_winsock.cpp @@ -61,6 +61,8 @@ int PacketPeerUDPWinsock::get_max_packet_size() const{ void PacketPeerUDPWinsock::_set_blocking(bool p_blocking) { + //am no windows expert + //hope this is the right thing if (blocking==p_blocking) return; diff --git a/scene/2d/particles_2d.cpp b/scene/2d/particles_2d.cpp index 7f492e743c0..6e2cf5954ba 100644 --- a/scene/2d/particles_2d.cpp +++ b/scene/2d/particles_2d.cpp @@ -355,6 +355,8 @@ void Particles2D::_process_particles(float p_delta) { p.rot=Math::deg2rad(param[PARAM_INITIAL_ANGLE]+param[PARAM_INITIAL_ANGLE]*randomness[PARAM_INITIAL_ANGLE]*_rand_from_seed(&rand_seed)); active_count++; + p.frame=Math::fmod(param[PARAM_ANIM_INITIAL_POS]+randomness[PARAM_ANIM_INITIAL_POS]*_rand_from_seed(&rand_seed),1.0); + } else { @@ -426,6 +428,8 @@ void Particles2D::_process_particles(float p_delta) { p.pos+=p.velocity*frame_time; p.rot+=Math::lerp(param[PARAM_SPIN_VELOCITY],param[PARAM_SPIN_VELOCITY]*randomness[PARAM_SPIN_VELOCITY]*_rand_from_seed(&rand_seed),randomness[PARAM_SPIN_VELOCITY])*frame_time; + float anim_spd=param[PARAM_ANIM_SPEED_SCALE]+param[PARAM_ANIM_SPEED_SCALE]*randomness[PARAM_ANIM_SPEED_SCALE]*_rand_from_seed(&rand_seed); + p.frame=Math::fposmod(p.frame+(frame_time/lifetime)*anim_spd,1.0); active_count++; @@ -474,9 +478,13 @@ void Particles2D::_notification(int p_what) { RID ci=get_canvas_item(); Size2 size(1,1); Point2 center; + int total_frames=1; if (!texture.is_null()) { size=texture->get_size(); + size.x/=h_frames; + size.y/=v_frames; + total_frames=h_frames*v_frames; } @@ -612,7 +620,17 @@ void Particles2D::_notification(int p_what) { if (texrid.is_valid()) { - texture->draw(ci,Point2(),color); + Rect2 src_rect; + src_rect.size=size; + + if (total_frames>1) { + int frame = Math::fast_ftoi(Math::floor(p.frame*total_frames)) % total_frames; + src_rect.pos.x = size.x * (frame%h_frames); + src_rect.pos.y = size.y * (frame/h_frames); + } + + + texture->draw_rect_region(ci,Rect2(Point2(),size),src_rect,color); //VisualServer::get_singleton()->canvas_item_add_texture_rect(ci,r,texrid,false,color); } else { VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2(),size),color); @@ -642,7 +660,9 @@ static const char* _particlesframe_property_names[Particles2D::PARAM_MAX]={ "params/initial_angle", "params/initial_size", "params/final_size", - "params/hue_variation" + "params/hue_variation", + "params/anim_speed_scale", + "params/anim_initial_pos", }; static const char* _particlesframe_property_rnames[Particles2D::PARAM_MAX]={ @@ -659,7 +679,9 @@ static const char* _particlesframe_property_rnames[Particles2D::PARAM_MAX]={ "randomness/initial_angle", "randomness/initial_size", "randomness/final_size", - "randomness/hue_variation" + "randomness/hue_variation", + "randomness/anim_speed_scale", + "randomness/anim_initial_pos", }; static const char* _particlesframe_property_ranges[Particles2D::PARAM_MAX]={ @@ -676,7 +698,9 @@ static const char* _particlesframe_property_ranges[Particles2D::PARAM_MAX]={ "0,360,0.01", "0,1024,0.01", "0,1024,0.01", - "0,1,0.01" + "0,1,0.01", + "0,128,0.01", + "0,1,0.01", }; @@ -909,6 +933,28 @@ bool Particles2D::is_flipped_v() const{ return flip_v; } +void Particles2D::set_h_frames(int p_frames) { + + ERR_FAIL_COND(p_frames<1); + h_frames=p_frames; +} + +int Particles2D::get_h_frames() const{ + + return h_frames; +} + +void Particles2D::set_v_frames(int p_frames){ + + ERR_FAIL_COND(p_frames<1); + v_frames=p_frames; +} +int Particles2D::get_v_frames() const{ + + return v_frames; +} + + void Particles2D::set_emission_points(const DVector& p_points) { @@ -958,6 +1004,12 @@ void Particles2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_flip_v","enable"),&Particles2D::set_flip_v); ObjectTypeDB::bind_method(_MD("is_flipped_v"),&Particles2D::is_flipped_v); + ObjectTypeDB::bind_method(_MD("set_h_frames","enable"),&Particles2D::set_h_frames); + ObjectTypeDB::bind_method(_MD("get_h_frames"),&Particles2D::get_h_frames); + + ObjectTypeDB::bind_method(_MD("set_v_frames","enable"),&Particles2D::set_v_frames); + ObjectTypeDB::bind_method(_MD("get_v_frames"),&Particles2D::get_v_frames); + ObjectTypeDB::bind_method(_MD("set_emission_half_extents","extents"),&Particles2D::set_emission_half_extents); ObjectTypeDB::bind_method(_MD("get_emission_half_extents"),&Particles2D::get_emission_half_extents); @@ -997,6 +1049,9 @@ void Particles2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL,"config/flip_h"),_SCS("set_flip_h"),_SCS("is_flipped_h")); ADD_PROPERTY(PropertyInfo(Variant::BOOL,"config/flip_v"),_SCS("set_flip_v"),_SCS("is_flipped_v")); ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"config/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture")); + ADD_PROPERTY(PropertyInfo(Variant::INT,"config/h_frames",PROPERTY_HINT_RANGE,"1,512,1"),_SCS("set_h_frames"),_SCS("get_h_frames")); + ADD_PROPERTY(PropertyInfo(Variant::INT,"config/v_frames",PROPERTY_HINT_RANGE,"1,512,1"),_SCS("set_v_frames"),_SCS("get_v_frames")); + for(int i=0;i particles; @@ -146,6 +149,8 @@ private: float time_scale; bool flip_h; bool flip_v; + int h_frames; + int v_frames; Point2 emissor_offset; Vector2 initial_velocity; Vector2 extents; @@ -206,6 +211,13 @@ public: void set_flip_v(bool p_flip); bool is_flipped_v() const; + + void set_h_frames(int p_frames); + int get_h_frames() const; + + void set_v_frames(int p_frames); + int get_v_frames() const; + void set_color_phases(int p_phases); int get_color_phases() const; diff --git a/scene/3d/navigation.cpp b/scene/3d/navigation.cpp index d22198d47e4..ce002fb44b3 100644 --- a/scene/3d/navigation.cpp +++ b/scene/3d/navigation.cpp @@ -182,6 +182,41 @@ void Navigation::navmesh_remove(int p_id){ } +void Navigation::_clip_path(Vector& path, Polygon *from_poly, const Vector3& p_to_point, Polygon* p_to_poly) { + + Vector3 from = path[path.size()-1]; + + if (from.distance_to(p_to_point)prev_edge; + Vector3 a = _get_vertex(from_poly->edges[pe].point); + Vector3 b = _get_vertex(from_poly->edges[(pe+1)%from_poly->edges.size()].point); + + from_poly=from_poly->edges[pe].C; + ERR_FAIL_COND(!from_poly); + + if (a.distance_to(b)>CMP_EPSILON) { + + Vector3 inters; + if (cut_plane.intersects_segment(a,b,&inters)) { + if (inters.distance_to(p_to_point)>CMP_EPSILON && inters.distance_to(path[path.size()-1])>CMP_EPSILON) { + path.push_back(inters); + } + } + } + } +} + Vector Navigation::get_simple_path(const Vector3& p_start, const Vector3& p_end, bool p_optimize) { @@ -379,9 +414,12 @@ Vector Navigation::get_simple_path(const Vector3& p_start, const Vector portal_left=left; } else { - apex_point=portal_right; + _clip_path(path,apex_poly,portal_right,right_poly); + + apex_point=portal_right; p=right_poly; left_poly=p; + apex_poly=p; portal_left=apex_point; portal_right=apex_point; path.push_back(apex_point); @@ -396,9 +434,12 @@ Vector Navigation::get_simple_path(const Vector3& p_start, const Vector portal_right=right; } else { + _clip_path(path,apex_poly,portal_left,left_poly); + apex_point=portal_left; p=left_poly; right_poly=p; + apex_poly=p; portal_right=apex_point; portal_left=apex_point; path.push_back(apex_point); diff --git a/scene/3d/navigation.h b/scene/3d/navigation.h index 9b6cf5fbc4d..69d48531a71 100644 --- a/scene/3d/navigation.h +++ b/scene/3d/navigation.h @@ -118,6 +118,7 @@ class Navigation : public Spatial { int last_id; Vector3 up; + void _clip_path(Vector& path,Polygon *from_poly, const Vector3& p_to_point, Polygon* p_to_poly); protected: