improved animation editor
-same-value link keys -new layout -forward, backwards playback -integrated curve/property editor -auto increment sprite frame after insert -copy & paste animation resoucres
|  | @ -995,12 +995,44 @@ Variant Object::get_meta(const String& p_name) const { | |||
| 	return metadata[p_name]; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| Array Object::_get_property_list_bind() const { | ||||
| 
 | ||||
| 	List<PropertyInfo> lpi; | ||||
| 	get_property_list(&lpi); | ||||
| 	return convert_property_list(&lpi); | ||||
| } | ||||
| 
 | ||||
| Array Object::_get_method_list_bind() const { | ||||
| 
 | ||||
| 	List<MethodInfo> ml; | ||||
| 	get_method_list(&ml); | ||||
| 	Array ret; | ||||
| 
 | ||||
| 	for(List<MethodInfo>::Element *E=ml.front();E;E=E->next()) { | ||||
| 
 | ||||
| 		Dictionary d; | ||||
| 		d["name"]=E->get().name; | ||||
| 		d["args"]=convert_property_list(&E->get().arguments); | ||||
| 		Array da; | ||||
| 		for(int i=0;i<E->get().default_arguments.size();i++) | ||||
| 			da.push_back(E->get().default_arguments[i]); | ||||
| 		d["default_args"]=da; | ||||
| 		d["flags"]=E->get().flags; | ||||
| 		d["id"]=E->get().id; | ||||
| 		Dictionary r; | ||||
| 		r["type"]=E->get().return_val.type; | ||||
| 		r["hint"]=E->get().return_val.hint; | ||||
| 		r["hint_string"]=E->get().return_val.hint_string; | ||||
| 		d["return_type"]=r; | ||||
| 		//va.push_back(d);
 | ||||
| 		ret.push_back(d); | ||||
| 	} | ||||
| 
 | ||||
| 	return ret; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| DVector<String> Object::_get_meta_list_bind() const { | ||||
| 
 | ||||
| 	DVector<String> _metaret; | ||||
|  | @ -1439,6 +1471,7 @@ void Object::_bind_methods() { | |||
| 	ObjectTypeDB::bind_method(_MD("set","property","value"),&Object::_set_bind); | ||||
| 	ObjectTypeDB::bind_method(_MD("get","property"),&Object::_get_bind); | ||||
| 	ObjectTypeDB::bind_method(_MD("get_property_list"),&Object::_get_property_list_bind); | ||||
| 	ObjectTypeDB::bind_method(_MD("get_method_list"),&Object::_get_method_list_bind); | ||||
| 	ObjectTypeDB::bind_method(_MD("notification","what"),&Object::notification,DEFVAL(false)); | ||||
| 	ObjectTypeDB::bind_method(_MD("get_instance_ID"),&Object::get_instance_ID); | ||||
| 
 | ||||
|  |  | |||
|  | @ -54,6 +54,7 @@ enum PropertyHint { | |||
| 	PROPERTY_HINT_ENUM, ///< hint_text= "val1,val2,val3,etc"
 | ||||
| 	PROPERTY_HINT_EXP_EASING, /// exponential easing funciton (Math::ease)
 | ||||
| 	PROPERTY_HINT_LENGTH, ///< hint_text= "length" (as integer)
 | ||||
| 	PROPERTY_HINT_SPRITE_FRAME, | ||||
| 	PROPERTY_HINT_KEY_ACCEL, ///< hint_text= "length" (as integer)
 | ||||
| 	PROPERTY_HINT_FLAGS, ///< hint_text= "flag1,flag2,etc" (as bit flags)
 | ||||
| 	PROPERTY_HINT_ALL_FLAGS, | ||||
|  | @ -448,6 +449,7 @@ protected: | |||
| 
 | ||||
| 	DVector<String> _get_meta_list_bind() const; | ||||
| 	Array _get_property_list_bind() const; | ||||
| 	Array _get_method_list_bind() const; | ||||
| 
 | ||||
| public: //should be protected, but bug in clang++
 | ||||
| 	static void initialize_type(); | ||||
|  |  | |||
|  | @ -31,7 +31,20 @@ | |||
| 
 | ||||
| void MainLoop::_bind_methods() { | ||||
| 
 | ||||
| 	ObjectTypeDB::bind_method("input_event",&MainLoop::input_event); | ||||
| 	ObjectTypeDB::bind_method(_MD("input_event","ev"),&MainLoop::input_event); | ||||
| 	ObjectTypeDB::bind_method(_MD("input_text","text"),&MainLoop::input_text); | ||||
| 	ObjectTypeDB::bind_method(_MD("init"),&MainLoop::init); | ||||
| 	ObjectTypeDB::bind_method(_MD("iteration","delta"),&MainLoop::iteration); | ||||
| 	ObjectTypeDB::bind_method(_MD("idle","delta"),&MainLoop::idle); | ||||
| 	ObjectTypeDB::bind_method(_MD("finish"),&MainLoop::finish); | ||||
| 
 | ||||
| 	BIND_VMETHOD( MethodInfo("_input_event",PropertyInfo(Variant::INPUT_EVENT,"ev")) ); | ||||
| 	BIND_VMETHOD( MethodInfo("_input_text",PropertyInfo(Variant::STRING,"text")) ); | ||||
| 	BIND_VMETHOD( MethodInfo("_initialize") ); | ||||
| 	BIND_VMETHOD( MethodInfo("_iteration",PropertyInfo(Variant::REAL,"delta")) ); | ||||
| 	BIND_VMETHOD( MethodInfo("_idle",PropertyInfo(Variant::REAL,"delta")) ); | ||||
| 	BIND_VMETHOD( MethodInfo("_finalize") ); | ||||
| 
 | ||||
| 
 | ||||
| 	BIND_CONSTANT(NOTIFICATION_WM_FOCUS_IN); | ||||
| 	BIND_CONSTANT(NOTIFICATION_WM_FOCUS_OUT); | ||||
|  | @ -58,13 +71,15 @@ MainLoop::~MainLoop() | |||
| 
 | ||||
| void MainLoop::input_text( const String& p_text ) { | ||||
| 
 | ||||
| 	if (get_script_instance()) | ||||
| 		get_script_instance()->call("_input_text",p_text); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| void MainLoop::input_event( const InputEvent& p_event ) { | ||||
| 
 | ||||
| 	if (get_script_instance()) | ||||
| 		get_script_instance()->call("input_event",p_event); | ||||
| 		get_script_instance()->call("_input_event",p_event); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
|  | @ -74,13 +89,13 @@ void MainLoop::init() { | |||
| 		set_script(init_script.get_ref_ptr()); | ||||
| 
 | ||||
| 	if (get_script_instance()) | ||||
| 		get_script_instance()->call("init"); | ||||
| 		get_script_instance()->call("_initialize"); | ||||
| 
 | ||||
| } | ||||
| bool MainLoop::iteration(float p_time) { | ||||
| 
 | ||||
| 	if (get_script_instance()) | ||||
| 		return get_script_instance()->call("iteration",p_time); | ||||
| 		return get_script_instance()->call("_iteration",p_time); | ||||
| 
 | ||||
| 	return false; | ||||
| 
 | ||||
|  | @ -88,14 +103,14 @@ bool MainLoop::iteration(float p_time) { | |||
| bool MainLoop::idle(float p_time) { | ||||
| 
 | ||||
| 	if (get_script_instance()) | ||||
| 		return get_script_instance()->call("idle",p_time); | ||||
| 		return get_script_instance()->call("_idle",p_time); | ||||
| 
 | ||||
| 	return false; | ||||
| } | ||||
| void MainLoop::finish() { | ||||
| 
 | ||||
| 	if (get_script_instance()) { | ||||
| 		get_script_instance()->call("finish"); | ||||
| 		get_script_instance()->call("_finalize"); | ||||
| 		set_script(RefPtr()); //clear script
 | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -329,7 +329,7 @@ void AnimatedSprite::_bind_methods() { | |||
| 	ADD_SIGNAL(MethodInfo("frame_changed")); | ||||
| 
 | ||||
| 	ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "frames",PROPERTY_HINT_RESOURCE_TYPE,"SpriteFrames"), _SCS("set_sprite_frames"),_SCS("get_sprite_frames")); | ||||
| 	ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "frame"), _SCS("set_frame"),_SCS("get_frame")); | ||||
| 	ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame")); | ||||
| 	ADD_PROPERTY( PropertyInfo( Variant::BOOL, "centered"), _SCS("set_centered"),_SCS("is_centered")); | ||||
| 	ADD_PROPERTYNZ( PropertyInfo( Variant::VECTOR2, "offset"), _SCS("set_offset"),_SCS("get_offset")); | ||||
| 	ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flip_h"), _SCS("set_flip_h"),_SCS("is_flipped_h")); | ||||
|  |  | |||
|  | @ -320,7 +320,7 @@ void Sprite::_bind_methods() { | |||
| 	ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flip_v"), _SCS("set_flip_v"),_SCS("is_flipped_v")); | ||||
| 	ADD_PROPERTY( PropertyInfo( Variant::INT, "vframes"), _SCS("set_vframes"),_SCS("get_vframes")); | ||||
| 	ADD_PROPERTY( PropertyInfo( Variant::INT, "hframes"), _SCS("set_hframes"),_SCS("get_hframes")); | ||||
| 	ADD_PROPERTY( PropertyInfo( Variant::INT, "frame"), _SCS("set_frame"),_SCS("get_frame")); | ||||
| 	ADD_PROPERTY( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame")); | ||||
| 	ADD_PROPERTY( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate")); | ||||
| 	ADD_PROPERTY( PropertyInfo( Variant::BOOL, "region"), _SCS("set_region"),_SCS("is_region")); | ||||
| 	ADD_PROPERTY( PropertyInfo( Variant::RECT2, "region_rect"), _SCS("set_region_rect"),_SCS("get_region_rect")); | ||||
|  |  | |||
|  | @ -580,7 +580,7 @@ void Sprite3D::_bind_methods() { | |||
| 	ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_texture"),_SCS("get_texture")); | ||||
| 	ADD_PROPERTY( PropertyInfo( Variant::INT, "vframes"), _SCS("set_vframes"),_SCS("get_vframes")); | ||||
| 	ADD_PROPERTY( PropertyInfo( Variant::INT, "hframes"), _SCS("set_hframes"),_SCS("get_hframes")); | ||||
| 	ADD_PROPERTY( PropertyInfo( Variant::INT, "frame"), _SCS("set_frame"),_SCS("get_frame")); | ||||
| 	ADD_PROPERTY( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame")); | ||||
| 	ADD_PROPERTY( PropertyInfo( Variant::BOOL, "region"), _SCS("set_region"),_SCS("is_region")); | ||||
| 	ADD_PROPERTY( PropertyInfo( Variant::RECT2, "region_rect"), _SCS("set_region_rect"),_SCS("get_region_rect")); | ||||
| 
 | ||||
|  | @ -727,7 +727,7 @@ void AnimatedSprite3D::_bind_methods(){ | |||
| 	ObjectTypeDB::bind_method(_MD("get_frame"),&AnimatedSprite3D::get_frame); | ||||
| 
 | ||||
| 	ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "frames", PROPERTY_HINT_RESOURCE_TYPE,"SpriteFrames"), _SCS("set_sprite_frames"),_SCS("get_sprite_frames")); | ||||
| 	ADD_PROPERTY( PropertyInfo( Variant::INT, "frame"), _SCS("set_frame"),_SCS("get_frame")); | ||||
| 	ADD_PROPERTY( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame")); | ||||
| 
 | ||||
| 	ADD_SIGNAL(MethodInfo("frame_changed")); | ||||
| 
 | ||||
|  |  | |||
|  | @ -967,11 +967,13 @@ String AnimationPlayer::get_current_animation() const { | |||
| 
 | ||||
| } | ||||
| 
 | ||||
| void AnimationPlayer::stop() { | ||||
| void AnimationPlayer::stop(bool p_reset) { | ||||
| 	 | ||||
| 	Playback &c=playback; | ||||
| 	c.blend.clear(); | ||||
| 	if (p_reset) { | ||||
| 		c.current.from=NULL; | ||||
| 	} | ||||
| 	_set_process(false); | ||||
| 	queued.clear(); | ||||
| 	playing = false; | ||||
|  | @ -1211,7 +1213,7 @@ void AnimationPlayer::_bind_methods() { | |||
| 	ObjectTypeDB::bind_method(_MD("get_default_blend_time"),&AnimationPlayer::get_default_blend_time); | ||||
| 
 | ||||
| 	ObjectTypeDB::bind_method(_MD("play","name","custom_blend","custom_speed","from_end"),&AnimationPlayer::play,DEFVAL(""),DEFVAL(-1),DEFVAL(1.0),DEFVAL(false)); | ||||
| 	ObjectTypeDB::bind_method(_MD("stop"),&AnimationPlayer::stop); | ||||
| 	ObjectTypeDB::bind_method(_MD("stop","reset"),&AnimationPlayer::stop,DEFVAL(true)); | ||||
| 	ObjectTypeDB::bind_method(_MD("stop_all"),&AnimationPlayer::stop_all); | ||||
| 	ObjectTypeDB::bind_method(_MD("is_playing"),&AnimationPlayer::is_playing); | ||||
| 	ObjectTypeDB::bind_method(_MD("set_current_animation","anim"),&AnimationPlayer::set_current_animation); | ||||
|  |  | |||
|  | @ -260,7 +260,7 @@ public: | |||
| 	void play(const StringName& p_name=StringName(),float p_custom_blend=-1,float p_custom_scale=1.0,bool p_from_end=false); | ||||
| 	void queue(const StringName& p_name); | ||||
| 	void clear_queue(); | ||||
| 	void stop(); | ||||
| 	void stop(bool p_reset=true); | ||||
| 	bool is_playing() const; | ||||
| 	String get_current_animation() const; | ||||
| 	void set_current_animation(const String& p_anim); | ||||
|  |  | |||
|  | @ -44,11 +44,207 @@ | |||
| */ | ||||
| 
 | ||||
| 
 | ||||
| class AnimationCurveEdit : public Control { | ||||
| 	OBJ_TYPE( AnimationCurveEdit, Control ); | ||||
| public: | ||||
| 	enum Mode { | ||||
| 		MODE_DISABLED, | ||||
| 		MODE_SINGLE, | ||||
| 		MODE_MULTIPLE | ||||
| 	}; | ||||
| private: | ||||
| 
 | ||||
| 	Set<float> multiples; | ||||
| 	float transition; | ||||
| 	Mode mode; | ||||
| 
 | ||||
| 	void _notification(int p_what) { | ||||
| 
 | ||||
| 		if (p_what==NOTIFICATION_DRAW) { | ||||
| 
 | ||||
| 
 | ||||
| 			RID ci = get_canvas_item(); | ||||
| 
 | ||||
| 			Size2 s = get_size(); | ||||
| 			Rect2 r(Point2(),s); | ||||
| 
 | ||||
| 			//r=r.grow(3);
 | ||||
| 			Ref<StyleBox> sb = get_stylebox("normal","LineEdit"); | ||||
| 			sb->draw(ci,r); | ||||
| 			r.size-=sb->get_minimum_size(); | ||||
| 			r.pos+=sb->get_offset(); | ||||
| 			//VisualServer::get_singleton()->canvas_item_add
 | ||||
| 
 | ||||
| 			Ref<Font> f = get_font("font","Label"); | ||||
| 			r=r.grow(-2); | ||||
| 			Color color = get_color("font_color","Label"); | ||||
| 
 | ||||
| 			int points = 48; | ||||
| 			if (mode==MODE_MULTIPLE) { | ||||
| 
 | ||||
| 				int max_draw = 16; | ||||
| 				Color mcolor=color; | ||||
| 				mcolor.a*=0.3; | ||||
| 
 | ||||
| 				Set<float>::Element *E=multiples.front(); | ||||
| 				for(int j=0;j<16;j++) { | ||||
| 
 | ||||
| 					if (!E) | ||||
| 						break; | ||||
| 
 | ||||
| 					float prev=1.0; | ||||
| 					float exp=E->get(); | ||||
| 					bool flip=false;//hint_text=="attenuation";
 | ||||
| 
 | ||||
| 
 | ||||
| 					for(int i=1;i<=points;i++) { | ||||
| 
 | ||||
| 						float ifl = i/float(points); | ||||
| 						float iflp = (i-1)/float(points); | ||||
| 
 | ||||
| 						float h = 1.0-Math::ease(ifl,exp); | ||||
| 
 | ||||
| 						if (flip) { | ||||
| 							ifl=1.0-ifl; | ||||
| 							iflp=1.0-iflp; | ||||
| 						} | ||||
| 
 | ||||
| 						VisualServer::get_singleton()->canvas_item_add_line(ci,r.pos+Point2(iflp*r.size.width,prev*r.size.height),r.pos+Point2(ifl*r.size.width,h*r.size.height),mcolor); | ||||
| 						prev=h; | ||||
| 					} | ||||
| 
 | ||||
| 					E=E->next(); | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			float exp=transition; | ||||
| 			if (mode!=MODE_DISABLED) { | ||||
| 
 | ||||
| 
 | ||||
| 				float prev=1.0; | ||||
| 
 | ||||
| 				bool flip=false;//hint_text=="attenuation";
 | ||||
| 
 | ||||
| 
 | ||||
| 				for(int i=1;i<=points;i++) { | ||||
| 
 | ||||
| 					float ifl = i/float(points); | ||||
| 					float iflp = (i-1)/float(points); | ||||
| 
 | ||||
| 					float h = 1.0-Math::ease(ifl,exp); | ||||
| 
 | ||||
| 					if (flip) { | ||||
| 						ifl=1.0-ifl; | ||||
| 						iflp=1.0-iflp; | ||||
| 					} | ||||
| 
 | ||||
| 					VisualServer::get_singleton()->canvas_item_add_line(ci,r.pos+Point2(iflp*r.size.width,prev*r.size.height),r.pos+Point2(ifl*r.size.width,h*r.size.height),color); | ||||
| 					prev=h; | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			String txt=String::num(exp,2); | ||||
| 			if (mode==MODE_DISABLED) { | ||||
| 				txt="Disabled"; | ||||
| 			} else if (mode==MODE_MULTIPLE) { | ||||
| 				txt+=" - All Selection"; | ||||
| 			} | ||||
| 
 | ||||
| 			f->draw(ci,Point2(10,10+f->get_ascent()),txt,color); | ||||
| 
 | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	void _input_event(const InputEvent& p_ev) { | ||||
| 		if (p_ev.type==InputEvent::MOUSE_MOTION && p_ev.mouse_motion.button_mask&BUTTON_MASK_LEFT) { | ||||
| 
 | ||||
| 			if (mode==MODE_DISABLED) | ||||
| 				return; | ||||
| 
 | ||||
| 			float rel = p_ev.mouse_motion.relative_x; | ||||
| 			if (rel==0) | ||||
| 			    return; | ||||
| 
 | ||||
| 			bool flip=false; | ||||
| 
 | ||||
| 			if (flip) | ||||
| 				rel=-rel; | ||||
| 
 | ||||
| 			float val = transition; | ||||
| 			if (val==0) | ||||
| 				return; | ||||
| 			bool sg = val < 0; | ||||
| 			val = Math::absf(val); | ||||
| 
 | ||||
| 			val = Math::log(val)/Math::log(2); | ||||
| 			//logspace
 | ||||
| 			val+=rel*0.05; | ||||
| 			//
 | ||||
| 
 | ||||
| 			val = Math::pow(2,val); | ||||
| 			if (sg) | ||||
| 				val=-val; | ||||
| 
 | ||||
| 			transition=val; | ||||
| 			update(); | ||||
| 			//emit_signal("variant_changed");
 | ||||
| 			emit_signal("transition_changed",transition); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
| 	static void _bind_methods() { | ||||
| 
 | ||||
| 	//	ObjectTypeDB::bind_method("_update_obj",&AnimationKeyEdit::_update_obj);
 | ||||
| 		ObjectTypeDB::bind_method("_input_event",&AnimationCurveEdit::_input_event); | ||||
| 		ADD_SIGNAL(MethodInfo("transition_changed")); | ||||
| 	} | ||||
| 
 | ||||
| 	void set_mode(Mode p_mode) { | ||||
| 
 | ||||
| 		mode=p_mode; | ||||
| 		update(); | ||||
| 	} | ||||
| 
 | ||||
| 	void clear_multiples() { multiples.clear(); update();} | ||||
| 	void set_multiple(float p_transition) { | ||||
| 
 | ||||
| 		multiples.insert(p_transition); | ||||
| 	} | ||||
| 
 | ||||
| 	void set_transition(float p_transition) { | ||||
| 		transition=p_transition; | ||||
| 		update(); | ||||
| 	} | ||||
| 
 | ||||
| 	float get_transition() const { | ||||
| 		return transition; | ||||
| 	} | ||||
| 
 | ||||
| 	void force_transition(float p_value) { | ||||
| 		if (mode==MODE_DISABLED) | ||||
| 			return; | ||||
| 		transition=p_value; | ||||
| 		emit_signal("transition_changed",p_value); | ||||
| 		update(); | ||||
| 	} | ||||
| 
 | ||||
| 	AnimationCurveEdit() { | ||||
| 
 | ||||
| 		transition=1.0; | ||||
| 		set_default_cursor_shape(CURSOR_HSPLIT); | ||||
| 		mode=MODE_DISABLED; | ||||
| 	} | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| class AnimationKeyEdit : public Object { | ||||
| 
 | ||||
| 	OBJ_TYPE(AnimationKeyEdit,Object); | ||||
| public: | ||||
| 	bool setting; | ||||
| 	bool hidden; | ||||
| 
 | ||||
| 	static void _bind_methods() { | ||||
| 
 | ||||
|  | @ -56,12 +252,12 @@ public: | |||
| 		ObjectTypeDB::bind_method("_key_ofs_changed",&AnimationKeyEdit::_key_ofs_changed); | ||||
| 	} | ||||
| 
 | ||||
| 	PopupDialog *ke_dialog; | ||||
| 	//PopupDialog *ke_dialog;
 | ||||
| 
 | ||||
| 	void _update_obj(const Ref<Animation> &p_anim) { | ||||
| 		if (setting) | ||||
| 			return; | ||||
| 		if (!ke_dialog->is_visible()) | ||||
| 		if (hidden) | ||||
| 			return; | ||||
| 		if (!(animation==p_anim)) | ||||
| 			return; | ||||
|  | @ -69,7 +265,7 @@ public: | |||
| 	} | ||||
| 
 | ||||
| 	void _key_ofs_changed(const Ref<Animation> &p_anim,float from, float to) { | ||||
| 		if (!ke_dialog->is_visible()) | ||||
| 		if (hidden) | ||||
| 			return; | ||||
| 		if (!(animation==p_anim)) | ||||
| 			return; | ||||
|  | @ -408,8 +604,8 @@ public: | |||
| 			} break; | ||||
| 		} | ||||
| 
 | ||||
| 		if (animation->track_get_type(track)!=Animation::TYPE_METHOD) | ||||
| 			p_list->push_back( PropertyInfo( Variant::REAL, "easing", PROPERTY_HINT_EXP_EASING)); | ||||
| 		//if (animation->track_get_type(track)!=Animation::TYPE_METHOD)
 | ||||
| 		//	p_list->push_back( PropertyInfo( Variant::REAL, "easing", PROPERTY_HINT_EXP_EASING));
 | ||||
| 	} | ||||
| 
 | ||||
| 	UndoRedo *undo_redo; | ||||
|  | @ -425,7 +621,7 @@ public: | |||
| 		_change_notify(); | ||||
| 	} | ||||
| 
 | ||||
| 	AnimationKeyEdit() { key_ofs=0; track=-1; setting=false; } | ||||
| 	AnimationKeyEdit() { hidden=true; key_ofs=0; track=-1; setting=false; } | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
|  | @ -610,6 +806,8 @@ void AnimationKeyEditor::_menu_track(int p_type) { | |||
| 
 | ||||
| 				selection=new_selection; | ||||
| 				track_editor->update(); | ||||
| 				_edit_if_single_selection(); | ||||
| 
 | ||||
| 
 | ||||
| 			} | ||||
| 
 | ||||
|  | @ -689,8 +887,31 @@ void AnimationKeyEditor::_menu_track(int p_type) { | |||
| 
 | ||||
| 			optimize_dialog->popup_centered(Size2(250,180)); | ||||
| 		} break; | ||||
| 		case CURVE_SET_LINEAR: { | ||||
| 			curve_edit->force_transition(1.0); | ||||
| 
 | ||||
| 		} break; | ||||
| 		case CURVE_SET_IN: { | ||||
| 
 | ||||
| 			curve_edit->force_transition(4.0); | ||||
| 
 | ||||
| 		} break; | ||||
| 		case CURVE_SET_OUT: { | ||||
| 
 | ||||
| 			curve_edit->force_transition(0.25); | ||||
| 		} break; | ||||
| 		case CURVE_SET_INOUT: { | ||||
| 			curve_edit->force_transition(-4); | ||||
| 
 | ||||
| 		} break; | ||||
| 		case CURVE_SET_OUTIN: { | ||||
| 
 | ||||
| 			curve_edit->force_transition(-0.25); | ||||
| 		} break; | ||||
| 		case CURVE_SET_CONSTANT: { | ||||
| 
 | ||||
| 			curve_edit->force_transition(0); | ||||
| 		} break; | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
|  | @ -774,6 +995,7 @@ void AnimationKeyEditor::_track_editor_draw() { | |||
| 		h_scroll->hide(); | ||||
| 		menu_track->set_disabled(true); | ||||
| 		edit_button->set_disabled(true); | ||||
| 		key_editor_tab->hide(); | ||||
| 		move_up_button->set_disabled(true); | ||||
| 		move_down_button->set_disabled(true); | ||||
| 		remove_button->set_disabled(true); | ||||
|  | @ -785,6 +1007,8 @@ void AnimationKeyEditor::_track_editor_draw() { | |||
| 	move_up_button->set_disabled(false); | ||||
| 	move_down_button->set_disabled(false); | ||||
| 	remove_button->set_disabled(false); | ||||
| 	if (edit_button->is_pressed()) | ||||
| 		key_editor_tab->show(); | ||||
| 
 | ||||
| 	te_drawing=true; | ||||
| 
 | ||||
|  | @ -1000,8 +1224,13 @@ void AnimationKeyEditor::_track_editor_draw() { | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	Color sep_color=color; | ||||
| 	color.a*=0.5; | ||||
| 
 | ||||
| 	for(int i=0;i<fit;i++) { | ||||
| 
 | ||||
| 		//this code sucks, i always forget how it works
 | ||||
| 
 | ||||
| 		int idx = v_scroll->get_val() + i; | ||||
| 		if (idx>=animation->get_track_count()) | ||||
| 			break; | ||||
|  | @ -1090,6 +1319,7 @@ void AnimationKeyEditor::_track_editor_draw() { | |||
| 		float key_hofs = -Math::floor(type_icon[tt]->get_height()/2); | ||||
| 
 | ||||
| 		int kc=animation->track_get_key_count(idx); | ||||
| 		bool first=true; | ||||
| 
 | ||||
| 		for(int i=0;i<kc;i++) { | ||||
| 
 | ||||
|  | @ -1116,7 +1346,22 @@ void AnimationKeyEditor::_track_editor_draw() { | |||
| 			if (mouse_over.over==MouseOver::OVER_KEY && mouse_over.track==idx && mouse_over.over_key==i) | ||||
| 				tex=type_hover; | ||||
| 
 | ||||
| 			Variant value = animation->track_get_key_value(idx,i); | ||||
| 			if (first && i>0 && value==animation->track_get_key_value(idx,i-1)) { | ||||
| 
 | ||||
| 				te->draw_line(ofs+Vector2(name_limit,y+h/2),ofs+Point2(x,y+h/2),color); | ||||
| 			} | ||||
| 
 | ||||
| 			if (i<kc-1 && value==animation->track_get_key_value(idx,i+1)) { | ||||
| 				float x_n =  key_hofs + name_limit + (animation->track_get_key_time(idx,i+1)-keys_from)*zoom_scale; | ||||
| 
 | ||||
| 				x_n = MIN( x_n, settings_limit); | ||||
| 				te->draw_line(ofs+Point2(x_n,y+h/2),ofs+Point2(x,y+h/2),color); | ||||
| 
 | ||||
| 			} | ||||
| 
 | ||||
| 			te->draw_texture(tex,ofs+Point2(x,y+key_vofs).floor()); | ||||
| 			first=false; | ||||
| 		} | ||||
| 
 | ||||
| 	} | ||||
|  | @ -1226,7 +1471,9 @@ void AnimationKeyEditor::_clear_selection_for_anim(const Ref<Animation>& p_anim) | |||
| 
 | ||||
| 	if (!(animation==p_anim)) | ||||
| 		return; | ||||
| 	selection.clear(); | ||||
| 	//selection.clear();
 | ||||
| 	_clear_selection(); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| void AnimationKeyEditor::_select_at_anim(const Ref<Animation>& p_anim,int p_track,float p_pos){ | ||||
|  | @ -1244,6 +1491,7 @@ void AnimationKeyEditor::_select_at_anim(const Ref<Animation>& p_anim,int p_trac | |||
| 	ki.pos=p_pos; | ||||
| 
 | ||||
| 	selection.insert(sk,ki); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -1283,6 +1531,83 @@ PropertyInfo AnimationKeyEditor::_find_hint_for_track(int p_idx) { | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| void AnimationKeyEditor::_curve_transition_changed(float p_what) { | ||||
| 
 | ||||
| 	if (selection.size()==0) | ||||
| 		return; | ||||
| 	if (selection.size()==1) | ||||
| 		undo_redo->create_action("Edit Node Curve",true); | ||||
| 	else | ||||
| 		undo_redo->create_action("Edit Selection Curve",true); | ||||
| 
 | ||||
| 	for(Map<SelectedKey,KeyInfo>::Element *E=selection.front();E;E=E->next()) { | ||||
| 
 | ||||
| 		int track = E->key().track; | ||||
| 		int key = E->key().key; | ||||
| 		float prev_val = animation->track_get_key_transition(track,key); | ||||
| 		undo_redo->add_do_method(animation.ptr(),"track_set_key_transition",track,key,p_what); | ||||
| 		undo_redo->add_undo_method(animation.ptr(),"track_set_key_transition",track,key,prev_val); | ||||
| 	} | ||||
| 
 | ||||
| 	undo_redo->commit_action(); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| void AnimationKeyEditor::_toggle_edit_curves() { | ||||
| 
 | ||||
| 	if (edit_button->is_pressed()) | ||||
| 		key_editor_tab->show(); | ||||
| 	else | ||||
| 		key_editor_tab->hide(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| bool AnimationKeyEditor::_edit_if_single_selection() { | ||||
| 
 | ||||
| 	if (selection.size()!=1) { | ||||
| 
 | ||||
| 		if (selection.size()==0) { | ||||
| 			curve_edit->set_mode(AnimationCurveEdit::MODE_DISABLED); | ||||
| 			print_line("disable"); | ||||
| 		} else { | ||||
| 
 | ||||
| 			curve_edit->set_mode(AnimationCurveEdit::MODE_MULTIPLE); | ||||
| 			curve_edit->set_transition(1.0); | ||||
| 			curve_edit->clear_multiples(); | ||||
| 			//add all
 | ||||
| 			for(Map<SelectedKey,KeyInfo>::Element *E=selection.front();E;E=E->next()) { | ||||
| 
 | ||||
| 				curve_edit->set_multiple(animation->track_get_key_transition(E->key().track,E->key().key)); | ||||
| 			} | ||||
| 			print_line("multiple"); | ||||
| 
 | ||||
| 		} | ||||
| 		return false; | ||||
| 	} | ||||
| 	curve_edit->set_mode(AnimationCurveEdit::MODE_SINGLE); | ||||
| 	print_line("regular"); | ||||
| 
 | ||||
| 	int idx = selection.front()->key().track; | ||||
| 	int key = selection.front()->key().key; | ||||
| 	{ | ||||
| 
 | ||||
| 		key_edit->animation=animation; | ||||
| 		key_edit->track=idx; | ||||
| 		key_edit->key_ofs=animation->track_get_key_time(idx,key); | ||||
| 		key_edit->hint=_find_hint_for_track(idx); | ||||
| 		key_edit->notify_change(); | ||||
| 
 | ||||
| 		curve_edit->set_transition(animation->track_get_key_transition(idx,key)); | ||||
| 
 | ||||
| 		/*key_edit_dialog->set_size( Size2( 200,200) );
 | ||||
| 		key_edit_dialog->set_pos(  track_editor->get_global_pos() + ofs + mpos +Point2(-100,20)); | ||||
| 		key_edit_dialog->popup();*/ | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 	return true; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { | ||||
| 
 | ||||
|  | @ -1364,9 +1689,12 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { | |||
| 						undo_redo->add_undo_method(animation.ptr(),"track_insert_key",E->key().track,E->get().pos,animation->track_get_key_value(E->key().track,E->key().key),animation->track_get_key_transition(E->key().track,E->key().key)); | ||||
| 
 | ||||
| 					} | ||||
| 					undo_redo->add_do_method(this,"_clear_selection_for_anim",animation); | ||||
| 					undo_redo->add_undo_method(this,"_clear_selection_for_anim",animation); | ||||
| 					undo_redo->commit_action(); | ||||
| 					selection.clear(); | ||||
| 					//selection.clear();
 | ||||
| 					accept_event(); | ||||
| 					_edit_if_single_selection(); | ||||
| 				} | ||||
| 			} else if (animation.is_valid() && animation->get_track_count()>0) { | ||||
| 
 | ||||
|  | @ -1552,20 +1880,7 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { | |||
| 
 | ||||
| 						} | ||||
| 
 | ||||
| 						if (mb.mod.command || edit_button->is_pressed()) { | ||||
| 
 | ||||
| 							key_edit->animation=animation; | ||||
| 							key_edit->track=idx; | ||||
| 							key_edit->key_ofs=animation->track_get_key_time(idx,key); | ||||
| 							key_edit->hint=_find_hint_for_track(idx); | ||||
| 
 | ||||
| 							key_edit->notify_change();							 | ||||
| 
 | ||||
| 							key_edit_dialog->set_size( Size2( 200,200) ); | ||||
| 							key_edit_dialog->set_pos(  track_editor->get_global_pos() + ofs + mpos +Point2(-100,20)); | ||||
| 							key_edit_dialog->popup(); | ||||
| 
 | ||||
| 						} | ||||
| 
 | ||||
| 						SelectedKey sk; | ||||
| 						sk.track=idx; | ||||
|  | @ -1577,7 +1892,7 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { | |||
| 
 | ||||
| 
 | ||||
| 						if (!mb.mod.shift && !selection.has(sk)) | ||||
| 							selection.clear(); | ||||
| 							_clear_selection(); | ||||
| 
 | ||||
| 						selection.insert(sk,ki); | ||||
| 
 | ||||
|  | @ -1588,7 +1903,10 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { | |||
| 						selected_track=idx; | ||||
| 						track_editor->update(); | ||||
| 
 | ||||
| 
 | ||||
| 						if (_edit_if_single_selection() && mb.mod.command) { | ||||
| 							edit_button->set_pressed(true); | ||||
| 							key_editor_tab->show(); | ||||
| 						} | ||||
| 					} else { | ||||
| 						//button column
 | ||||
| 						int ofsx = size.width - mpos.x; | ||||
|  | @ -1824,7 +2142,8 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { | |||
| 
 | ||||
| 							if (from_track>to_track) { | ||||
| 								if (!click.shift) | ||||
| 									selection.clear(); | ||||
| 									_clear_selection(); | ||||
| 								_edit_if_single_selection(); | ||||
| 								break; | ||||
| 							} | ||||
| 
 | ||||
|  | @ -1842,12 +2161,13 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { | |||
| 
 | ||||
| 							if (from_track > tracks_to  || to_track < tracks_from) { | ||||
| 								if (!click.shift) | ||||
| 									selection.clear(); | ||||
| 									_clear_selection(); | ||||
| 								_edit_if_single_selection(); | ||||
| 								break; | ||||
| 							} | ||||
| 
 | ||||
| 							if (!click.shift) | ||||
| 								selection.clear(); | ||||
| 								_clear_selection(); | ||||
| 
 | ||||
| 
 | ||||
| 							int higher_track=0x7FFFFFFF; | ||||
|  | @ -1880,6 +2200,8 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { | |||
| 							} | ||||
| 
 | ||||
| 
 | ||||
| 							_edit_if_single_selection(); | ||||
| 
 | ||||
| 
 | ||||
| 						} break; | ||||
| 						case ClickOver::CLICK_MOVE_KEYS: { | ||||
|  | @ -1891,8 +2213,9 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { | |||
| 								if (!click.shift) { | ||||
| 
 | ||||
| 									KeyInfo ki=selection[click.selk]; | ||||
| 									selection.clear(); | ||||
| 									_clear_selection(); | ||||
| 									selection[click.selk]=ki; | ||||
| 									_edit_if_single_selection(); | ||||
| 								} | ||||
| 
 | ||||
| 								break; | ||||
|  | @ -2007,6 +2330,7 @@ void AnimationKeyEditor::_track_editor_input_event(const InputEvent& p_input) { | |||
| 							} | ||||
| 
 | ||||
| 							undo_redo->commit_action(); | ||||
| 							_edit_if_single_selection(); | ||||
| 
 | ||||
| 						} break; | ||||
| 						default: {} | ||||
|  | @ -2348,20 +2672,33 @@ void AnimationKeyEditor::_notification(int p_what) { | |||
| 				optimize_dialog->connect("confirmed",this,"_animation_optimize"); | ||||
| 
 | ||||
| 				menu_track->get_popup()->add_child(tpp); | ||||
| 				menu_track->get_popup()->add_submenu_item("Set Transitions..","Transitions"); | ||||
| 				menu_track->get_popup()->add_separator(); | ||||
| 				//menu_track->get_popup()->add_submenu_item("Set Transitions..","Transitions");
 | ||||
| 				//menu_track->get_popup()->add_separator();
 | ||||
| 				menu_track->get_popup()->add_item("Optimize Animation",TRACK_MENU_OPTIMIZE); | ||||
| 
 | ||||
| 				curve_linear->set_icon(get_icon("CurveLinear","EditorIcons")); | ||||
| 				curve_in->set_icon(get_icon("CurveIn","EditorIcons")); | ||||
| 				curve_out->set_icon(get_icon("CurveOut","EditorIcons")); | ||||
| 				curve_inout->set_icon(get_icon("CurveInOut","EditorIcons")); | ||||
| 				curve_outin->set_icon(get_icon("CurveOutIn","EditorIcons")); | ||||
| 				curve_constant->set_icon(get_icon("CurveConstant","EditorIcons")); | ||||
| 
 | ||||
| 
 | ||||
| 				curve_linear->connect("pressed",this,"_menu_track",varray(CURVE_SET_LINEAR)); | ||||
| 				curve_in->connect("pressed",this,"_menu_track",varray(CURVE_SET_IN)); | ||||
| 				curve_out->connect("pressed",this,"_menu_track",varray(CURVE_SET_OUT)); | ||||
| 				curve_inout->connect("pressed",this,"_menu_track",varray(CURVE_SET_INOUT)); | ||||
| 				curve_outin->connect("pressed",this,"_menu_track",varray(CURVE_SET_OUTIN)); | ||||
| 				curve_constant->connect("pressed",this,"_menu_track",varray(CURVE_SET_CONSTANT)); | ||||
| 
 | ||||
| 
 | ||||
| 				move_up_button->set_icon(get_icon("MoveUp","EditorIcons")); | ||||
| 				move_down_button->set_icon(get_icon("MoveDown","EditorIcons")); | ||||
| 				remove_button->set_icon(get_icon("Remove","EditorIcons")); | ||||
| 				edit_button->set_icon(get_icon("EditKey","EditorIcons")); | ||||
| 				edit_button->connect("pressed",this,"_toggle_edit_curves"); | ||||
| 
 | ||||
| 				loop->set_icon(get_icon("Loop","EditorIcons")); | ||||
| 				curve_edit->connect("transition_changed",this,"_curve_transition_changed"); | ||||
| 
 | ||||
| 				//edit_button->add_color_override("font_color",get_color("font_color","Tree"));
 | ||||
| 				//edit_button->add_color_override("font_color_hover",get_color("font_color","Tree"));
 | ||||
|  | @ -2456,6 +2793,17 @@ void AnimationKeyEditor::_update_menu() { | |||
| 	updating=false; | ||||
| 
 | ||||
| } | ||||
| void AnimationKeyEditor::_clear_selection() { | ||||
| 
 | ||||
| 	selection.clear(); | ||||
| 	key_edit->animation=Ref<Animation>(); | ||||
| 	key_edit->track=0; | ||||
| 	key_edit->key_ofs=0; | ||||
| 	key_edit->hint=PropertyInfo(); | ||||
| 	key_edit->notify_change(); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void AnimationKeyEditor::set_animation(const Ref<Animation>& p_anim) { | ||||
| 
 | ||||
|  | @ -2466,11 +2814,12 @@ void AnimationKeyEditor::set_animation(const Ref<Animation>& p_anim) { | |||
| 		animation->connect("changed",this,"_update_paths"); | ||||
| 
 | ||||
| 	timeline_pos=0; | ||||
| 	selection.clear(); | ||||
| 	_clear_selection(); | ||||
| 	_update_paths(); | ||||
| 
 | ||||
| 	_update_menu(); | ||||
| 	selected_track=-1; | ||||
| 	_edit_if_single_selection(); | ||||
| } | ||||
| 
 | ||||
| void AnimationKeyEditor::set_root(Node *p_root) { | ||||
|  | @ -2591,6 +2940,7 @@ void AnimationKeyEditor::insert_transform_key(Spatial *p_node,const String& p_su | |||
| 	id.value=p_xform; | ||||
| 	id.type=Animation::TYPE_TRANSFORM; | ||||
| 	id.query="node '"+p_node->get_name()+"'"; | ||||
| 	id.advance=false; | ||||
| 
 | ||||
| 	//dialog insert
 | ||||
| 
 | ||||
|  | @ -2643,6 +2993,7 @@ void AnimationKeyEditor::insert_node_value_key(Node* p_node, const String& p_pro | |||
| 	id.value=p_value; | ||||
| 	id.type=Animation::TYPE_VALUE; | ||||
| 	id.query="property '"+p_property+"'"; | ||||
| 	id.advance=false; | ||||
| 	//dialog insert
 | ||||
| 	_query_insert(id); | ||||
| 
 | ||||
|  | @ -2650,7 +3001,7 @@ void AnimationKeyEditor::insert_node_value_key(Node* p_node, const String& p_pro | |||
| 
 | ||||
| } | ||||
| 
 | ||||
| void AnimationKeyEditor::insert_value_key(const String& p_property,const Variant& p_value) { | ||||
| void AnimationKeyEditor::insert_value_key(const String& p_property,const Variant& p_value,bool p_advance) { | ||||
| 
 | ||||
| 	ERR_FAIL_COND(!root); | ||||
| 	//let's build a node path
 | ||||
|  | @ -2696,6 +3047,7 @@ void AnimationKeyEditor::insert_value_key(const String& p_property,const Variant | |||
| 	id.value=p_value; | ||||
| 	id.type=Animation::TYPE_VALUE; | ||||
| 	id.query="property '"+p_property+"'"; | ||||
| 	id.advance=p_advance; | ||||
| 	//dialog insert
 | ||||
| 	_query_insert(id); | ||||
| 
 | ||||
|  | @ -2928,13 +3280,31 @@ void AnimationKeyEditor::_insert_delay() { | |||
| 	undo_redo->create_action("Anim  Insert"); | ||||
| 
 | ||||
| 	int last_track = animation->get_track_count(); | ||||
| 	bool advance=false; | ||||
| 	while(insert_data.size()) { | ||||
| 
 | ||||
| 		if (insert_data.front()->get().advance) | ||||
| 			advance=true; | ||||
| 		last_track=_confirm_insert(insert_data.front()->get(),last_track); | ||||
| 		insert_data.pop_front(); | ||||
| 	} | ||||
| 
 | ||||
| 	undo_redo->commit_action(); | ||||
| 
 | ||||
| 	if (advance) { | ||||
| 		float step = animation->get_step(); | ||||
| 		if (step==0) | ||||
| 			step=1; | ||||
| 
 | ||||
| 		float pos=timeline_pos; | ||||
| 
 | ||||
| 		pos=Math::stepify(pos+step,step); | ||||
| 		if (pos>animation->get_length()) | ||||
| 			pos=animation->get_length(); | ||||
| 		timeline_pos=pos; | ||||
| 		track_pos->update(); | ||||
| 		emit_signal("timeline_changed",pos); | ||||
| 	} | ||||
| 	insert_queue=false; | ||||
| } | ||||
| 
 | ||||
|  | @ -3122,12 +3492,15 @@ void AnimationKeyEditor::_bind_methods() { | |||
| 
 | ||||
| 	ObjectTypeDB::bind_method(_MD("set_animation"),&AnimationKeyEditor::set_animation); | ||||
| 	ObjectTypeDB::bind_method(_MD("_animation_optimize"),&AnimationKeyEditor::_animation_optimize); | ||||
| 	ObjectTypeDB::bind_method(_MD("_curve_transition_changed"),&AnimationKeyEditor::_curve_transition_changed); | ||||
| 	ObjectTypeDB::bind_method(_MD("_toggle_edit_curves"),&AnimationKeyEditor::_toggle_edit_curves); | ||||
| 
 | ||||
| 
 | ||||
| 	ADD_SIGNAL( MethodInfo("resource_selected", PropertyInfo( Variant::OBJECT, "res"),PropertyInfo( Variant::STRING, "prop") ) ); | ||||
| 	ADD_SIGNAL( MethodInfo("keying_changed" ) ); | ||||
| 	ADD_SIGNAL( MethodInfo("timeline_changed", PropertyInfo(Variant::REAL,"pos") ) ); | ||||
| 	ADD_SIGNAL( MethodInfo("animation_len_changed", PropertyInfo(Variant::REAL,"len") ) ); | ||||
| 	ADD_SIGNAL( MethodInfo("key_edited", PropertyInfo(Variant::INT,"track"), PropertyInfo(Variant::INT,"key") ) ); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
|  | @ -3219,12 +3592,6 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h | |||
| 
 | ||||
| 	hb->add_child( memnew( VSeparator ) ); | ||||
| 
 | ||||
| 	edit_button = memnew( ToolButton ); | ||||
| 	edit_button->set_toggle_mode(true); | ||||
| 	edit_button->set_focus_mode(FOCUS_NONE); | ||||
| 	edit_button->set_disabled(true); | ||||
| 	hb->add_child(edit_button); | ||||
| 	edit_button->set_tooltip("Enable editing of individual keys by clicking them."); | ||||
| 
 | ||||
| 	move_up_button = memnew( ToolButton ); | ||||
| 	hb->add_child(move_up_button); | ||||
|  | @ -3247,6 +3614,15 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h | |||
| 	remove_button->set_disabled(true); | ||||
| 	remove_button->set_tooltip("Remove selected track."); | ||||
| 
 | ||||
| 	hb->add_child(memnew( VSeparator )); | ||||
| 
 | ||||
| 	edit_button = memnew( ToolButton ); | ||||
| 	edit_button->set_toggle_mode(true); | ||||
| 	edit_button->set_focus_mode(FOCUS_NONE); | ||||
| 	edit_button->set_disabled(true); | ||||
| 
 | ||||
| 	hb->add_child(edit_button); | ||||
| 	edit_button->set_tooltip("Enable editing of individual keys by clicking them."); | ||||
| 
 | ||||
| 	optimize_dialog = memnew( ConfirmationDialog ); | ||||
| 	add_child(optimize_dialog); | ||||
|  | @ -3297,7 +3673,7 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h | |||
| //	menu->get_popup()->connect("item_pressed",this,"_menu_callback");
 | ||||
| 
 | ||||
| 	ec = memnew (Control); | ||||
| 	ec->set_custom_minimum_size(Size2(0,50)); | ||||
| 	ec->set_custom_minimum_size(Size2(0,150)); | ||||
| 	add_child(ec); | ||||
| 	ec->set_v_size_flags(SIZE_EXPAND_FILL); | ||||
| 
 | ||||
|  | @ -3313,6 +3689,7 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h | |||
| 	track_editor->set_focus_mode(Control::FOCUS_ALL); | ||||
| 	track_editor->set_h_size_flags(SIZE_EXPAND_FILL); | ||||
| 
 | ||||
| 
 | ||||
| 	track_pos = memnew( Control ); | ||||
| 	track_pos->set_area_as_parent_rect(); | ||||
| 	track_pos->set_ignore_mouse(true); | ||||
|  | @ -3325,6 +3702,56 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h | |||
| 	v_scroll->connect("value_changed",this,"_scroll_changed"); | ||||
| 	v_scroll->set_val(0); | ||||
| 
 | ||||
| 	key_editor_tab = memnew(TabContainer); | ||||
| 	hb->add_child(key_editor_tab); | ||||
| 	key_editor_tab->set_custom_minimum_size(Size2(200,0)); | ||||
| 
 | ||||
| 	key_editor = memnew( PropertyEditor ); | ||||
| 	key_editor->set_area_as_parent_rect(); | ||||
| 	key_editor->hide_top_label(); | ||||
| 	key_editor->set_name("Key"); | ||||
| 	key_editor_tab->add_child(key_editor); | ||||
| 
 | ||||
| 	key_edit = memnew( AnimationKeyEdit ); | ||||
| 	key_edit->undo_redo=undo_redo; | ||||
| 	//key_edit->ke_dialog=key_edit_dialog;
 | ||||
| 	key_editor->edit(key_edit); | ||||
| 	type_menu = memnew( PopupMenu ); | ||||
| 	add_child(type_menu); | ||||
| 	for(int i=0;i<Variant::VARIANT_MAX;i++) | ||||
| 		type_menu->add_item(Variant::get_type_name(Variant::Type(i)),i); | ||||
| 	type_menu->connect("item_pressed",this,"_create_value_item"); | ||||
| 
 | ||||
| 	VBoxContainer *curve_vb = memnew( VBoxContainer ); | ||||
| 	curve_vb->set_name("Transition"); | ||||
| 	HBoxContainer *curve_hb = memnew( HBoxContainer ); | ||||
| 	curve_vb->add_child(curve_hb); | ||||
| 
 | ||||
| 	curve_linear = memnew( ToolButton ); | ||||
| 	curve_linear->set_focus_mode(FOCUS_NONE); | ||||
| 	curve_hb->add_child(curve_linear); | ||||
| 	curve_in = memnew( ToolButton ); | ||||
| 	curve_in->set_focus_mode(FOCUS_NONE); | ||||
| 	curve_hb->add_child(curve_in); | ||||
| 	curve_out = memnew( ToolButton ); | ||||
| 	curve_out->set_focus_mode(FOCUS_NONE); | ||||
| 	curve_hb->add_child(curve_out); | ||||
| 	curve_inout = memnew( ToolButton ); | ||||
| 	curve_inout->set_focus_mode(FOCUS_NONE); | ||||
| 	curve_hb->add_child(curve_inout); | ||||
| 	curve_outin = memnew( ToolButton ); | ||||
| 	curve_outin->set_focus_mode(FOCUS_NONE); | ||||
| 	curve_hb->add_child(curve_outin); | ||||
| 	curve_constant = memnew( ToolButton ); | ||||
| 	curve_constant->set_focus_mode(FOCUS_NONE); | ||||
| 	curve_hb->add_child(curve_constant); | ||||
| 
 | ||||
| 
 | ||||
| 	curve_edit = memnew( AnimationCurveEdit ); | ||||
| 	curve_vb->add_child(curve_edit); | ||||
| 	curve_edit->set_v_size_flags(SIZE_EXPAND_FILL); | ||||
| 	key_editor_tab->add_child(curve_vb); | ||||
| 
 | ||||
| 	h_scroll = memnew( HScrollBar ); | ||||
| 	h_scroll->connect("value_changed",this,"_scroll_changed"); | ||||
| 	add_child(h_scroll); | ||||
|  | @ -3340,7 +3767,7 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h | |||
| 	add_child(track_menu); | ||||
| 	track_menu->connect("item_pressed",this,"_track_menu_selected"); | ||||
| 
 | ||||
| 
 | ||||
| 	key_editor_tab->hide(); | ||||
| 
 | ||||
| 	last_idx =1; | ||||
| 
 | ||||
|  | @ -3359,24 +3786,6 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h | |||
| 	timeline_pos=0; | ||||
| 
 | ||||
| 
 | ||||
| 	key_edit_dialog = memnew( PopupDialog ); | ||||
| 	key_editor = memnew( PropertyEditor ); | ||||
| 	add_child(key_edit_dialog); | ||||
| 	key_editor->set_area_as_parent_rect(); | ||||
| 	key_editor->hide_top_label(); | ||||
| 	for(int i=0;i<4;i++) | ||||
| 		key_editor->set_margin(Margin(i),5); | ||||
| 	key_edit_dialog->add_child(key_editor); | ||||
| 
 | ||||
| 	key_edit = memnew( AnimationKeyEdit ); | ||||
| 	key_edit->undo_redo=undo_redo; | ||||
| 	key_edit->ke_dialog=key_edit_dialog; | ||||
| 	key_editor->edit(key_edit); | ||||
| 	type_menu = memnew( PopupMenu ); | ||||
| 	add_child(type_menu); | ||||
| 	for(int i=0;i<Variant::VARIANT_MAX;i++) | ||||
| 		type_menu->add_item(Variant::get_type_name(Variant::Type(i)),i); | ||||
| 	type_menu->connect("item_pressed",this,"_create_value_item"); | ||||
| 	keying=false; | ||||
| 	insert_frame=0; | ||||
| 	insert_query=false; | ||||
|  |  | |||
|  | @ -37,6 +37,7 @@ | |||
| #include "scene/gui/scroll_bar.h" | ||||
| #include "scene/gui/tool_button.h" | ||||
| #include "scene/gui/file_dialog.h" | ||||
| #include "scene/gui/tab_container.h" | ||||
| 
 | ||||
| #include "scene/resources/animation.h" | ||||
| #include "scene/animation/animation_cache.h" | ||||
|  | @ -46,6 +47,7 @@ | |||
| 
 | ||||
| 
 | ||||
| class AnimationKeyEdit; | ||||
| class AnimationCurveEdit; | ||||
| 
 | ||||
| class AnimationKeyEditor : public VBoxContainer  { | ||||
| 
 | ||||
|  | @ -86,7 +88,13 @@ class AnimationKeyEditor : public VBoxContainer  { | |||
| 		TRACK_MENU_SET_ALL_TRANS_OUTIN, | ||||
| 		TRACK_MENU_NEXT_STEP, | ||||
| 		TRACK_MENU_PREV_STEP, | ||||
| 		TRACK_MENU_OPTIMIZE | ||||
| 		TRACK_MENU_OPTIMIZE, | ||||
| 		CURVE_SET_LINEAR, | ||||
| 		CURVE_SET_IN, | ||||
| 		CURVE_SET_OUT, | ||||
| 		CURVE_SET_INOUT, | ||||
| 		CURVE_SET_OUTIN, | ||||
| 		CURVE_SET_CONSTANT | ||||
| 	}; | ||||
| 
 | ||||
| 	struct MouseOver { | ||||
|  | @ -169,6 +177,14 @@ class AnimationKeyEditor : public VBoxContainer  { | |||
| 	ToolButton *move_down_button; | ||||
| 	ToolButton *remove_button; | ||||
| 
 | ||||
| 	ToolButton *curve_linear; | ||||
| 	ToolButton *curve_in; | ||||
| 	ToolButton *curve_out; | ||||
| 	ToolButton *curve_inout; | ||||
| 	ToolButton *curve_outin; | ||||
| 	ToolButton *curve_constant; | ||||
| 
 | ||||
| 
 | ||||
| 	ConfirmationDialog *optimize_dialog; | ||||
| 	SpinBox *optimize_linear_error; | ||||
| 	SpinBox *optimize_angular_error; | ||||
|  | @ -183,11 +199,11 @@ class AnimationKeyEditor : public VBoxContainer  { | |||
| 
 | ||||
| 	Control *track_editor; | ||||
| 	Control *track_pos; | ||||
| 	TabContainer *key_editor_tab; | ||||
| 
 | ||||
| 	ConfirmationDialog *scale_dialog; | ||||
| 	SpinBox *scale; | ||||
| 
 | ||||
| 	PopupDialog *key_edit_dialog; | ||||
| 	PropertyEditor *key_editor;	 | ||||
| 
 | ||||
| 	Ref<Animation> animation; | ||||
|  | @ -203,6 +219,7 @@ class AnimationKeyEditor : public VBoxContainer  { | |||
| 
 | ||||
| 
 | ||||
| 	AnimationKeyEdit *key_edit; | ||||
| 	AnimationCurveEdit *curve_edit; | ||||
| 
 | ||||
| 	bool inserting; | ||||
| 
 | ||||
|  | @ -220,6 +237,7 @@ class AnimationKeyEditor : public VBoxContainer  { | |||
| 		int track_idx; | ||||
| 		Variant value; | ||||
| 		String query; | ||||
| 		bool advance; | ||||
| 	};/* insert_data;*/ | ||||
| 
 | ||||
| 	bool insert_query; | ||||
|  | @ -254,7 +272,7 @@ class AnimationKeyEditor : public VBoxContainer  { | |||
| 	void _scale(); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 	void _clear_selection(); | ||||
| 
 | ||||
| 	//void _browse_path();
 | ||||
| 
 | ||||
|  | @ -270,12 +288,15 @@ class AnimationKeyEditor : public VBoxContainer  { | |||
| 
 | ||||
| 	void _clear_selection_for_anim(const Ref<Animation>& p_anim); | ||||
| 	void _select_at_anim(const Ref<Animation>& p_anim,int p_track,float p_pos); | ||||
| 	void _curve_transition_changed(float p_what); | ||||
| 
 | ||||
| 	PropertyInfo _find_hint_for_track(int p_idx); | ||||
| 
 | ||||
| 	void _create_value_item(int p_type); | ||||
| 	void _pane_drag(const Point2& p_delta); | ||||
| 	bool _edit_if_single_selection(); | ||||
| 
 | ||||
| 	void _toggle_edit_curves(); | ||||
| 	void _animation_len_update(); | ||||
| 
 | ||||
| 	void _root_removed(); | ||||
|  | @ -296,7 +317,7 @@ public: | |||
| 
 | ||||
| 	void set_anim_pos(float p_pos); | ||||
| 	void insert_node_value_key(Node* p_node, const String& p_property,const Variant& p_value,bool p_only_if_exists=false); | ||||
| 	void insert_value_key(const String& p_property,const Variant& p_value); | ||||
| 	void insert_value_key(const String& p_property, const Variant& p_value, bool p_advance); | ||||
| 	void insert_transform_key(Spatial *p_node,const String& p_sub,const Transform& p_xform); | ||||
| 
 | ||||
| 	AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_history, EditorSelection *p_selection); | ||||
|  |  | |||
|  | @ -989,6 +989,7 @@ EditorFileSystemDirectory *EditorFileSystem::get_path(const String& p_path) { | |||
| 
 | ||||
| void EditorFileSystem::_resource_saved(const String& p_path){ | ||||
| 
 | ||||
| 	print_line("resource saved: "+p_path); | ||||
| 	EditorFileSystem::get_singleton()->update_file(p_path); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -2838,9 +2838,9 @@ void EditorNode::_instance_request(const String& p_path){ | |||
| 	request_instance_scene(p_path); | ||||
| } | ||||
| 
 | ||||
| void EditorNode::_property_keyed(const String& p_keyed,const Variant& p_value) { | ||||
| void EditorNode::_property_keyed(const String& p_keyed,const Variant& p_value,bool p_advance) { | ||||
| 
 | ||||
| 	animation_editor->insert_value_key(p_keyed,p_value); | ||||
| 	animation_editor->insert_value_key(p_keyed,p_value,p_advance); | ||||
| } | ||||
| 
 | ||||
| void EditorNode::_transform_keyed(Object *sp,const String& p_sub,const Transform& p_key) { | ||||
|  |  | |||
|  | @ -348,7 +348,7 @@ class EditorNode : public Node { | |||
| 
 | ||||
| 	void _instance_request(const String& p_path); | ||||
| 
 | ||||
| 	void _property_keyed(const String& p_keyed,const Variant& p_value); | ||||
| 	void _property_keyed(const String& p_keyed, const Variant& p_value, bool p_advance); | ||||
| 	void _transform_keyed(Object *sp,const String& p_sub,const Transform& p_key); | ||||
| 
 | ||||
| 	void _update_keying(); | ||||
|  |  | |||
							
								
								
									
										
											BIN
										
									
								
								tools/editor/icons/icon_curve_constant.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 222 B | 
							
								
								
									
										
											BIN
										
									
								
								tools/editor/icons/icon_curve_in.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 319 B | 
							
								
								
									
										
											BIN
										
									
								
								tools/editor/icons/icon_curve_in_out.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 326 B | 
							
								
								
									
										
											BIN
										
									
								
								tools/editor/icons/icon_curve_linear.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 275 B | 
							
								
								
									
										
											BIN
										
									
								
								tools/editor/icons/icon_curve_out.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 319 B | 
							
								
								
									
										
											BIN
										
									
								
								tools/editor/icons/icon_curve_out_in.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 318 B | 
							
								
								
									
										
											BIN
										
									
								
								tools/editor/icons/icon_key_next.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 499 B | 
| Before Width: | Height: | Size: 367 B After Width: | Height: | Size: 228 B | 
| Before Width: | Height: | Size: 256 B After Width: | Height: | Size: 260 B | 
							
								
								
									
										
											BIN
										
									
								
								tools/editor/icons/icon_play_backwards.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 256 B | 
							
								
								
									
										
											BIN
										
									
								
								tools/editor/icons/icon_play_start.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 282 B | 
							
								
								
									
										
											BIN
										
									
								
								tools/editor/icons/icon_play_start_backwards.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 289 B | 
| Before Width: | Height: | Size: 138 B After Width: | Height: | Size: 236 B | 
|  | @ -28,7 +28,8 @@ | |||
| /*************************************************************************/ | ||||
| #include "animation_player_editor_plugin.h" | ||||
| #include "io/resource_loader.h" | ||||
| 
 | ||||
| #include "os/keyboard.h" | ||||
| #include "tools/editor/editor_settings.h" | ||||
| 
 | ||||
| void AnimationPlayerEditor::_node_removed(Node *p_node) { | ||||
| 
 | ||||
|  | @ -100,12 +101,18 @@ void AnimationPlayerEditor::_notification(int p_what) { | |||
| 		remove_anim->set_icon( get_icon("Del","EditorIcons") ); | ||||
| 		edit_anim->set_icon( get_icon("Edit","EditorIcons") ); | ||||
| 		blend_anim->set_icon( get_icon("Blend","EditorIcons") ); | ||||
| 		play->set_icon( get_icon("Play","EditorIcons") ); | ||||
| 		play->set_icon( get_icon("PlayStart","EditorIcons") ); | ||||
| 		play_from->set_icon( get_icon("Play","EditorIcons") ); | ||||
| 		play_bw->set_icon( get_icon("PlayStartBackwards","EditorIcons") ); | ||||
| 		play_bw_from->set_icon( get_icon("PlayBackwards","EditorIcons") ); | ||||
| 
 | ||||
| 		autoplay_icon=get_icon("AutoPlay","EditorIcons"); | ||||
| 		stop->set_icon( get_icon("Stop","EditorIcons") ); | ||||
| 		resource_edit_anim->set_icon( get_icon("EditResource","EditorIcons") ); | ||||
| 		pin->set_normal_texture(get_icon("Pin","EditorIcons") ); | ||||
| 		pin->set_pressed_texture( get_icon("PinPressed","EditorIcons") ); | ||||
| 		tool_anim->set_icon(get_icon("Tools","EditorIcons")); | ||||
| 		tool_anim->get_popup()->connect("item_pressed",this,"_animation_tool_menu"); | ||||
| 
 | ||||
| 		blend_editor.next->connect("text_changed",this,"_blend_editor_next_changed"); | ||||
| 
 | ||||
|  | @ -180,9 +187,82 @@ void AnimationPlayerEditor::_play_pressed() { | |||
| 	//unpause
 | ||||
| 	//pause->set_pressed(false);
 | ||||
| } | ||||
| 
 | ||||
| void AnimationPlayerEditor::_play_from_pressed() { | ||||
| 
 | ||||
| 	String current; | ||||
| 	if (animation->get_selected()>=0 && animation->get_selected()<animation->get_item_count()) { | ||||
| 
 | ||||
| 		current = animation->get_item_text( animation->get_selected() ); | ||||
| 	} | ||||
| 
 | ||||
| 	if (current!="") { | ||||
| 
 | ||||
| 		float time = player->get_current_animation_pos(); | ||||
| 
 | ||||
| 		if (current==player->get_current_animation() && player->is_playing()) { | ||||
| 
 | ||||
| 			player->stop(); //so it wont blend with itself
 | ||||
| 		} | ||||
| 
 | ||||
| 		player->play( current ); | ||||
| 		player->seek(time); | ||||
| 	} | ||||
| 
 | ||||
| 	//unstop
 | ||||
| 	stop->set_pressed(false); | ||||
| 	//unpause
 | ||||
| 	//pause->set_pressed(false);
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void AnimationPlayerEditor::_play_bw_pressed() { | ||||
| 
 | ||||
| 	String current; | ||||
| 	if (animation->get_selected()>=0 && animation->get_selected()<animation->get_item_count()) { | ||||
| 
 | ||||
| 		current = animation->get_item_text( animation->get_selected() ); | ||||
| 	} | ||||
| 
 | ||||
| 	if (current!="") { | ||||
| 
 | ||||
| 		if (current==player->get_current_animation()) | ||||
| 			player->stop(); //so it wont blend with itself
 | ||||
| 		player->play(current,-1,-1,true); | ||||
| 	} | ||||
| 
 | ||||
| 	//unstop
 | ||||
| 	stop->set_pressed(false); | ||||
| 	//unpause
 | ||||
| 	//pause->set_pressed(false);
 | ||||
| } | ||||
| 
 | ||||
| void AnimationPlayerEditor::_play_bw_from_pressed() { | ||||
| 
 | ||||
| 	String current; | ||||
| 	if (animation->get_selected()>=0 && animation->get_selected()<animation->get_item_count()) { | ||||
| 
 | ||||
| 		current = animation->get_item_text( animation->get_selected() ); | ||||
| 	} | ||||
| 
 | ||||
| 	if (current!="") { | ||||
| 
 | ||||
| 		float time = player->get_current_animation_pos(); | ||||
| 		if (current==player->get_current_animation()) | ||||
| 			player->stop(); //so it wont blend with itself
 | ||||
| 
 | ||||
| 		player->play(current,-1,-1,true); | ||||
| 		player->seek(time); | ||||
| 	} | ||||
| 
 | ||||
| 	//unstop
 | ||||
| 	stop->set_pressed(false); | ||||
| 	//unpause
 | ||||
| 	//pause->set_pressed(false);
 | ||||
| } | ||||
| void AnimationPlayerEditor::_stop_pressed() { | ||||
| 
 | ||||
| 	player->stop(); | ||||
| 	player->stop(false); | ||||
| 	play->set_pressed(false); | ||||
| 	stop->set_pressed(true); | ||||
| 	//pause->set_pressed(false);
 | ||||
|  | @ -598,6 +678,9 @@ void AnimationPlayerEditor::_update_player() { | |||
| 
 | ||||
| 	stop->set_disabled(animlist.size()==0); | ||||
| 	play->set_disabled(animlist.size()==0); | ||||
| 	play_bw->set_disabled(animlist.size()==0); | ||||
| 	play_bw_from->set_disabled(animlist.size()==0); | ||||
| 	play_from->set_disabled(animlist.size()==0); | ||||
| 	autoplay->set_disabled(animlist.size()==0); | ||||
| 	duplicate_anim->set_disabled(animlist.size()==0); | ||||
| 	rename_anim->set_disabled(animlist.size()==0); | ||||
|  | @ -877,11 +960,108 @@ void AnimationPlayerEditor::_hide_anim_editors() { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void AnimationPlayerEditor::_animation_tool_menu(int p_option) { | ||||
| 
 | ||||
| 	switch(p_option) { | ||||
| 
 | ||||
| 		case TOOL_COPY_ANIM: { | ||||
| 
 | ||||
| 			if (!animation->get_item_count()) { | ||||
| 				error_dialog->set_text("ERROR: No animation to copy!"); | ||||
| 				error_dialog->popup_centered_minsize(); | ||||
| 				return; | ||||
| 			} | ||||
| 
 | ||||
| 			String current = animation->get_item_text(animation->get_selected()); | ||||
| 			Ref<Animation> anim =  player->get_animation(current); | ||||
| 			//editor->edit_resource(anim);
 | ||||
| 			EditorSettings::get_singleton()->set_resource_clipboard(anim); | ||||
| 
 | ||||
| 		} break; | ||||
| 		case TOOL_PASTE_ANIM: { | ||||
| 
 | ||||
| 			Ref<Animation> anim = EditorSettings::get_singleton()->get_resource_clipboard(); | ||||
| 			if (!anim.is_valid()) { | ||||
| 				error_dialog->set_text("ERROR: No animation resource on clipboard!"); | ||||
| 				error_dialog->popup_centered_minsize(); | ||||
| 				return; | ||||
| 			} | ||||
| 
 | ||||
| 			String name = anim->get_name(); | ||||
| 			if (name=="") { | ||||
| 				name="Pasted Animation"; | ||||
| 			} | ||||
| 
 | ||||
| 			int idx=1; | ||||
| 			String base = name; | ||||
| 			while (player->has_animation(name)) { | ||||
| 
 | ||||
| 				idx++; | ||||
| 				name=base+" "+itos(idx); | ||||
| 			} | ||||
| 
 | ||||
| 			undo_redo->create_action("Paste Animation"); | ||||
| 			undo_redo->add_do_method(player,"add_animation",name,anim); | ||||
| 			undo_redo->add_undo_method(player,"remove_animation",name); | ||||
| 			undo_redo->add_do_method(this,"_animation_player_changed",player); | ||||
| 			undo_redo->add_undo_method(this,"_animation_player_changed",player); | ||||
| 			undo_redo->commit_action(); | ||||
| 
 | ||||
| 			_select_anim_by_name(name); | ||||
| 
 | ||||
| 
 | ||||
| 		} break; | ||||
| 		case TOOL_EDIT_RESOURCE: { | ||||
| 
 | ||||
| 			if (!animation->get_item_count()) { | ||||
| 				error_dialog->set_text("ERROR: No animation to edit!"); | ||||
| 				error_dialog->popup_centered_minsize(); | ||||
| 				return; | ||||
| 			} | ||||
| 
 | ||||
| 			String current = animation->get_item_text(animation->get_selected()); | ||||
| 			Ref<Animation> anim =  player->get_animation(current); | ||||
| 			editor->edit_resource(anim); | ||||
| 
 | ||||
| 		} break; | ||||
| 
 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void AnimationPlayerEditor::_unhandled_key_input(const InputEvent& p_ev) { | ||||
| 
 | ||||
| 	if (is_visible() && p_ev.type==InputEvent::KEY && p_ev.key.pressed && !p_ev.key.echo && !p_ev.key.mod.alt && !p_ev.key.mod.control && !p_ev.key.mod.meta) { | ||||
| 
 | ||||
| 		switch(p_ev.key.scancode) { | ||||
| 
 | ||||
| 			case KEY_A: { | ||||
| 				if (!p_ev.key.mod.shift) | ||||
| 					_play_bw_from_pressed(); | ||||
| 				else | ||||
| 					_play_bw_pressed(); | ||||
| 			} break; | ||||
| 			case KEY_S: { | ||||
| 				_stop_pressed(); | ||||
| 			} break; | ||||
| 			case KEY_D: { | ||||
| 				if (!p_ev.key.mod.shift) | ||||
| 					_play_from_pressed(); | ||||
| 				else | ||||
| 					_play_pressed(); | ||||
| 			} break; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void AnimationPlayerEditor::_bind_methods() { | ||||
| 
 | ||||
| 	ObjectTypeDB::bind_method(_MD("_input_event"),&AnimationPlayerEditor::_input_event); | ||||
| 	ObjectTypeDB::bind_method(_MD("_node_removed"),&AnimationPlayerEditor::_node_removed); | ||||
| 	ObjectTypeDB::bind_method(_MD("_play_pressed"),&AnimationPlayerEditor::_play_pressed); | ||||
| 	ObjectTypeDB::bind_method(_MD("_play_from_pressed"),&AnimationPlayerEditor::_play_from_pressed); | ||||
| 	ObjectTypeDB::bind_method(_MD("_play_bw_pressed"),&AnimationPlayerEditor::_play_bw_pressed); | ||||
| 	ObjectTypeDB::bind_method(_MD("_play_bw_from_pressed"),&AnimationPlayerEditor::_play_bw_from_pressed); | ||||
| 	ObjectTypeDB::bind_method(_MD("_stop_pressed"),&AnimationPlayerEditor::_stop_pressed); | ||||
| 	ObjectTypeDB::bind_method(_MD("_autoplay_pressed"),&AnimationPlayerEditor::_autoplay_pressed); | ||||
| 	ObjectTypeDB::bind_method(_MD("_pause_pressed"),&AnimationPlayerEditor::_pause_pressed); | ||||
|  | @ -908,6 +1088,8 @@ void AnimationPlayerEditor::_bind_methods() { | |||
| 	ObjectTypeDB::bind_method(_MD("_hide_anim_editors"),&AnimationPlayerEditor::_hide_anim_editors); | ||||
| 	ObjectTypeDB::bind_method(_MD("_animation_duplicate"),&AnimationPlayerEditor::_animation_duplicate); | ||||
| 	ObjectTypeDB::bind_method(_MD("_blend_editor_next_changed"),&AnimationPlayerEditor::_blend_editor_next_changed); | ||||
| 	ObjectTypeDB::bind_method(_MD("_unhandled_key_input"),&AnimationPlayerEditor::_unhandled_key_input); | ||||
| 	ObjectTypeDB::bind_method(_MD("_animation_tool_menu"),&AnimationPlayerEditor::_animation_tool_menu); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -935,47 +1117,56 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) { | |||
| 	add_child(hb); | ||||
| 
 | ||||
| 
 | ||||
| 	add_anim = memnew( Button ); | ||||
| 	add_anim = memnew( ToolButton ); | ||||
| 	add_anim->set_tooltip("Create new animation in player."); | ||||
| 
 | ||||
| 	hb->add_child(add_anim); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 	load_anim = memnew( Button ); | ||||
| 	load_anim = memnew( ToolButton ); | ||||
| 	load_anim->set_tooltip("Load an animation from disk."); | ||||
| 	hb->add_child(load_anim); | ||||
| 
 | ||||
| 	duplicate_anim = memnew( Button ); | ||||
| 	duplicate_anim = memnew( ToolButton ); | ||||
| 	hb->add_child(duplicate_anim); | ||||
| 	duplicate_anim->set_tooltip("Duplicate Animation"); | ||||
| 
 | ||||
| 	rename_anim = memnew( ToolButton ); | ||||
| 	hb->add_child(rename_anim); | ||||
| 	rename_anim->set_tooltip("Rename Animation"); | ||||
| 
 | ||||
| 	remove_anim = memnew( ToolButton ); | ||||
| 
 | ||||
| 	hb->add_child(remove_anim); | ||||
| 	remove_anim->set_tooltip("Remove Animation"); | ||||
| 
 | ||||
| 
 | ||||
| 	animation = memnew( OptionButton ); | ||||
| 	hb->add_child(animation); | ||||
| 	animation->set_h_size_flags(SIZE_EXPAND_FILL); | ||||
| 	animation->set_tooltip("Display list of animations in player."); | ||||
| 
 | ||||
| 	autoplay = memnew( Button ); | ||||
| 	autoplay = memnew( ToolButton ); | ||||
| 	hb->add_child(autoplay); | ||||
| 	autoplay->set_tooltip("Autoplay On Load"); | ||||
| 
 | ||||
| 
 | ||||
| 	rename_anim = memnew( Button ); | ||||
| 	hb->add_child(rename_anim); | ||||
| 	rename_anim->set_tooltip("Rename Animation"); | ||||
| 
 | ||||
| 	remove_anim = memnew( Button ); | ||||
| 
 | ||||
| 	hb->add_child(remove_anim); | ||||
| 	remove_anim->set_tooltip("Remove Animation"); | ||||
| 
 | ||||
| 	blend_anim = memnew( Button ); | ||||
| 	blend_anim = memnew( ToolButton ); | ||||
| 	hb->add_child(blend_anim); | ||||
| 	blend_anim->set_tooltip("Edit Target Blend Times"); | ||||
| 
 | ||||
| 	tool_anim = memnew( MenuButton); | ||||
| 	//tool_anim->set_flat(false);
 | ||||
| 	tool_anim->set_tooltip("Animation Tools"); | ||||
| 	tool_anim->get_popup()->add_item("Copy Animation",TOOL_COPY_ANIM); | ||||
| 	tool_anim->get_popup()->add_item("Paste Animation",TOOL_PASTE_ANIM); | ||||
| 	//tool_anim->get_popup()->add_separator();
 | ||||
| 	//tool_anim->get_popup()->add_item("Edit Anim Resource",TOOL_PASTE_ANIM);
 | ||||
| 	hb->add_child(tool_anim); | ||||
| 
 | ||||
| 
 | ||||
| 	edit_anim = memnew( Button ); | ||||
| 	edit_anim = memnew( ToolButton ); | ||||
| 	edit_anim->set_toggle_mode(true); | ||||
| 	hb->add_child(edit_anim); | ||||
| 	edit_anim->set_tooltip("Open animation editor.\nProperty editor will displays all editable keys too."); | ||||
|  | @ -984,15 +1175,29 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) { | |||
| 	hb = memnew (HBoxContainer); | ||||
| 	add_child(hb); | ||||
| 
 | ||||
| 	play = memnew( Button ); | ||||
| 	play->set_tooltip("Play selected animation."); | ||||
| 	play_bw_from = memnew( ToolButton ); | ||||
| 	play_bw_from->set_tooltip("Play backwards selected animation from current pos. (A)"); | ||||
| 	hb->add_child(play_bw_from); | ||||
| 
 | ||||
| 	hb->add_child(play); | ||||
| 	play_bw = memnew( ToolButton ); | ||||
| 	play_bw->set_tooltip("Play backwards selected animation from end. (Shift+A)"); | ||||
| 	hb->add_child(play_bw); | ||||
| 
 | ||||
| 	stop = memnew( Button ); | ||||
| 	stop = memnew( ToolButton ); | ||||
| 	stop->set_toggle_mode(true); | ||||
| 	hb->add_child(stop); | ||||
| 	play->set_tooltip("Stop animation playback."); | ||||
| 	stop->set_tooltip("Stop animation playback. (S)"); | ||||
| 
 | ||||
| 	play = memnew( ToolButton ); | ||||
| 	play->set_tooltip("Play selected animation from start. (Shift+D)"); | ||||
| 	hb->add_child(play); | ||||
| 
 | ||||
| 
 | ||||
| 	play_from = memnew( ToolButton ); | ||||
| 	play_from->set_tooltip("Play selected animation from current pos. (D)"); | ||||
| 	hb->add_child(play_from); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 	//pause = memnew( Button );
 | ||||
| 	//pause->set_toggle_mode(true);
 | ||||
|  | @ -1024,6 +1229,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) { | |||
| 
 | ||||
| 	resource_edit_anim= memnew( Button ); | ||||
| 	hb->add_child(resource_edit_anim); | ||||
| 	resource_edit_anim->hide(); | ||||
| 
 | ||||
| 
 | ||||
| 	file = memnew(FileDialog); | ||||
|  | @ -1075,6 +1281,9 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) { | |||
| 	autoplay->connect("pressed", this,"_autoplay_pressed"); | ||||
| 	autoplay->set_toggle_mode(true); | ||||
| 	play->connect("pressed", this,"_play_pressed"); | ||||
| 	play_from->connect("pressed", this,"_play_from_pressed"); | ||||
| 	play_bw->connect("pressed", this,"_play_bw_pressed"); | ||||
| 	play_bw_from->connect("pressed", this,"_play_bw_from_pressed"); | ||||
| 	stop->connect("pressed", this,"_stop_pressed"); | ||||
| 	//pause->connect("pressed", this,"_pause_pressed");
 | ||||
| 	add_anim->connect("pressed", this,"_animation_new"); | ||||
|  | @ -1104,6 +1313,8 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) { | |||
| 
 | ||||
| 	renaming=false; | ||||
| 	last_active=false; | ||||
| 
 | ||||
| 	set_process_unhandled_key_input(true); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -49,10 +49,19 @@ class AnimationPlayerEditor : public VBoxContainer { | |||
| 	EditorNode *editor; | ||||
| 	AnimationPlayer *player; | ||||
| 
 | ||||
| 	enum { | ||||
| 		TOOL_COPY_ANIM, | ||||
| 		TOOL_PASTE_ANIM, | ||||
| 		TOOL_EDIT_RESOURCE | ||||
| 	}; | ||||
| 
 | ||||
| 	OptionButton *animation; | ||||
| 	Button *stop; | ||||
| 	Button *play; | ||||
| 	Button *play_from; | ||||
| 	Button *play_bw; | ||||
| 	Button *play_bw_from; | ||||
| 
 | ||||
| //	Button *pause;
 | ||||
| 	Button *add_anim; | ||||
| 	Button *autoplay; | ||||
|  | @ -63,6 +72,7 @@ class AnimationPlayerEditor : public VBoxContainer { | |||
| 	Button *load_anim; | ||||
| 	Button *blend_anim; | ||||
| 	Button *remove_anim; | ||||
| 	MenuButton *tool_anim; | ||||
| 	TextureButton *pin; | ||||
| 	Label *nodename; | ||||
| 	SpinBox *frame; | ||||
|  | @ -95,6 +105,9 @@ class AnimationPlayerEditor : public VBoxContainer { | |||
| 
 | ||||
| 	void _select_anim_by_name(const String& p_anim); | ||||
| 	void _play_pressed(); | ||||
| 	void _play_from_pressed(); | ||||
| 	void _play_bw_pressed(); | ||||
| 	void _play_bw_from_pressed(); | ||||
| 	void _autoplay_pressed(); | ||||
| 	void _stop_pressed(); | ||||
| 	void _pause_pressed(); | ||||
|  | @ -126,6 +139,8 @@ class AnimationPlayerEditor : public VBoxContainer { | |||
| 
 | ||||
| 	void _animation_key_editor_seek(float p_pos); | ||||
| 	void _animation_key_editor_anim_len_changed(float p_new); | ||||
| 	void _unhandled_key_input(const InputEvent& p_ev); | ||||
| 	void _animation_tool_menu(int p_option); | ||||
| 
 | ||||
| 	AnimationPlayerEditor(); | ||||
| protected: | ||||
|  |  | |||
|  | @ -2629,8 +2629,13 @@ void PropertyEditor::update_tree() { | |||
| 
 | ||||
| 		if (keying) { | ||||
| 
 | ||||
| 			if (p.hint==PROPERTY_HINT_SPRITE_FRAME) { | ||||
| 
 | ||||
| 				item->add_button(1,get_icon("KeyNext","EditorIcons"),5); | ||||
| 			} else { | ||||
| 				item->add_button(1,get_icon("Key","EditorIcons"),2); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if (get_instanced_node()) { | ||||
| 
 | ||||
|  | @ -2904,6 +2909,16 @@ void PropertyEditor::edit(Object* p_object) { | |||
| 	 | ||||
| } | ||||
| 
 | ||||
| void PropertyEditor::_set_range_def(Object *p_item, String prop,float p_frame) { | ||||
| 
 | ||||
| 	TreeItem *ti = p_item->cast_to<TreeItem>(); | ||||
| 	ERR_FAIL_COND(!ti); | ||||
| 
 | ||||
| 	ti->call_deferred("set_range",1, p_frame); | ||||
| 	obj->call_deferred("set",prop,p_frame); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| void PropertyEditor::_edit_button(Object *p_item, int p_column, int p_button) { | ||||
| 	TreeItem *ti = p_item->cast_to<TreeItem>(); | ||||
| 	ERR_FAIL_COND(!ti); | ||||
|  | @ -2915,7 +2930,15 @@ void PropertyEditor::_edit_button(Object *p_item, int p_column, int p_button) { | |||
| 		if (!d.has("name")) | ||||
| 			return; | ||||
| 		String prop=d["name"]; | ||||
| 		emit_signal("property_keyed",prop,obj->get(prop)); | ||||
| 		emit_signal("property_keyed",prop,obj->get(prop),false); | ||||
| 	} else if (p_button==5) { | ||||
| 		print_line("PB5"); | ||||
| 		if (!d.has("name")) | ||||
| 			return; | ||||
| 		String prop=d["name"]; | ||||
| 		emit_signal("property_keyed",prop,obj->get(prop),true); | ||||
| 		//set_range(p_column, ti->get_range(p_column)+1.0 );
 | ||||
| 		call_deferred("_set_range_def",ti,prop,ti->get_range(p_column)+1.0); | ||||
| 	} else if (p_button==3) { | ||||
| 
 | ||||
| 		if (!get_instanced_node()) | ||||
|  | @ -3046,6 +3069,7 @@ void PropertyEditor::_bind_methods() { | |||
| 	ObjectTypeDB::bind_method( "_edit_button",&PropertyEditor::_edit_button); | ||||
| 	ObjectTypeDB::bind_method( "_changed_callback",&PropertyEditor::_changed_callbacks); | ||||
| 	ObjectTypeDB::bind_method( "_draw_flags",&PropertyEditor::_draw_flags); | ||||
| 	ObjectTypeDB::bind_method( "_set_range_def",&PropertyEditor::_set_range_def); | ||||
| 
 | ||||
| 	ADD_SIGNAL( MethodInfo("property_toggled",PropertyInfo( Variant::STRING, "property"),PropertyInfo( Variant::BOOL, "value"))); | ||||
| 	ADD_SIGNAL( MethodInfo("resource_selected", PropertyInfo( Variant::OBJECT, "res"),PropertyInfo( Variant::STRING, "prop") ) ); | ||||
|  |  | |||
|  | @ -187,6 +187,7 @@ class PropertyEditor : public Control { | |||
| 
 | ||||
| 	Node *get_instanced_node(); | ||||
| 	void _refresh_item(TreeItem *p_item); | ||||
| 	void _set_range_def(Object *p_item, String prop, float p_frame); | ||||
| 
 | ||||
| 	UndoRedo *undo_redo; | ||||
| protected: | ||||
|  |  | |||
 Juan Linietsky
						Juan Linietsky