Explorar el Código

-Modified Input and added is_action_just_pressed() as well as is_action_just_released()

Juan Linietsky hace 9 años
padre
commit
5b96c3a552

+ 4 - 0
core/input_map.cpp

@@ -290,6 +290,10 @@ bool InputMap::event_is_joy_motion_action_pressed(const InputEvent& p_event) con
 
 }
 
+const Map<StringName, InputMap::Action>& InputMap::get_action_map() const {
+	return input_map;
+}
+
 void InputMap::load_from_globals() {
 
 	input_map.clear();;

+ 5 - 3
core/input_map.h

@@ -35,12 +35,14 @@
 class InputMap : public Object {
 
 	OBJ_TYPE( InputMap, Object );
-	static InputMap *singleton;
-
+public:
 	struct Action {
 		int id;
 		List<InputEvent> inputs;
 	};
+private:
+	static InputMap *singleton;
+
 	mutable Map<StringName, Action> input_map;
 	mutable Map<int,StringName> input_id_map;
 
@@ -72,7 +74,7 @@ public:
 	bool event_is_action(const InputEvent& p_event, const StringName& p_action) const;
 	bool event_is_joy_motion_action_pressed(const InputEvent& p_event) const;
 
-
+	const Map<StringName, Action>& get_action_map() const;
 	void load_from_globals();
 	void load_default();
 

+ 2 - 0
core/os/input.cpp

@@ -53,6 +53,8 @@ void Input::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("is_mouse_button_pressed","button"),&Input::is_mouse_button_pressed);
 	ObjectTypeDB::bind_method(_MD("is_joy_button_pressed","device","button"),&Input::is_joy_button_pressed);
 	ObjectTypeDB::bind_method(_MD("is_action_pressed","action"),&Input::is_action_pressed);
+	ObjectTypeDB::bind_method(_MD("is_action_just_pressed","action"),&Input::is_action_just_pressed);
+	ObjectTypeDB::bind_method(_MD("is_action_just_released","action"),&Input::is_action_just_released);
 	ObjectTypeDB::bind_method(_MD("add_joy_mapping","mapping", "update_existing"),&Input::add_joy_mapping, DEFVAL(false));
 	ObjectTypeDB::bind_method(_MD("remove_joy_mapping","guid"),&Input::remove_joy_mapping);
 	ObjectTypeDB::bind_method(_MD("is_joy_known","device"),&Input::is_joy_known);

+ 11 - 9
core/os/input.h

@@ -55,12 +55,14 @@ public:
 
 	static Input *get_singleton();
 
-	virtual bool is_key_pressed(int p_scancode)=0;
-	virtual bool is_mouse_button_pressed(int p_button)=0;
-	virtual bool is_joy_button_pressed(int p_device, int p_button)=0;
-	virtual bool is_action_pressed(const StringName& p_action)=0;
-
-	virtual float get_joy_axis(int p_device,int p_axis)=0;
+	virtual bool is_key_pressed(int p_scancode) const=0;
+	virtual bool is_mouse_button_pressed(int p_button) const=0;
+	virtual bool is_joy_button_pressed(int p_device, int p_button) const=0;
+	virtual bool is_action_pressed(const StringName& p_action) const=0;
+	virtual bool is_action_just_pressed(const StringName& p_action) const=0;
+	virtual bool is_action_just_released(const StringName& p_action) const=0;
+
+	virtual float get_joy_axis(int p_device,int p_axis) const=0;
 	virtual String get_joy_name(int p_idx)=0;
 	virtual Array get_connected_joysticks()=0;
 	virtual void joy_connection_changed(int p_idx, bool p_connected, String p_name, String p_guid)=0;
@@ -80,9 +82,9 @@ public:
 
 	virtual void warp_mouse_pos(const Vector2& p_to)=0;
 
-	virtual Vector3 get_accelerometer()=0;
-	virtual Vector3 get_magnetometer()=0;
-	virtual Vector3 get_gyroscope()=0;
+	virtual Vector3 get_accelerometer() const=0;
+	virtual Vector3 get_magnetometer() const=0;
+	virtual Vector3 get_gyroscope() const=0;
 
 	virtual void action_press(const StringName& p_action)=0;
 	virtual void action_release(const StringName& p_action)=0;

+ 3 - 0
core/os/os.cpp

@@ -587,6 +587,9 @@ OS::OS() {
 	_time_scale=1.0;
 	_pixel_snap=false;
 	_allow_hidpi=true;
+	_fixed_frames=0;
+	_idle_frames=0;
+	_in_fixed=false;
 	Math::seed(1234567);
 }
 

+ 8 - 0
core/os/os.h

@@ -62,6 +62,10 @@ class OS {
 	bool _pixel_snap;
 	bool _allow_hidpi;
 
+	uint64_t _fixed_frames;
+	uint64_t _idle_frames;
+	bool _in_fixed;
+
 	char *last_error;
 
 public:
@@ -282,6 +286,10 @@ public:
 
 	uint64_t get_frames_drawn();
 
+	uint64_t get_fixed_frames() const { return _fixed_frames; }
+	uint64_t get_idle_frames() const { return _idle_frames; }
+	bool is_in_fixed_frame() const { return _in_fixed; }
+
 	bool is_stdout_verbose() const;
 
 	enum CursorShape {

+ 69 - 18
main/input_default.cpp

@@ -71,13 +71,13 @@ InputDefault::SpeedTrack::SpeedTrack() {
 	 reset();
 }
 
-bool InputDefault::is_key_pressed(int p_scancode) {
+bool InputDefault::is_key_pressed(int p_scancode) const {
 
 	_THREAD_SAFE_METHOD_
 	return keys_pressed.has(p_scancode);
 }
 
-bool InputDefault::is_mouse_button_pressed(int p_button) {
+bool InputDefault::is_mouse_button_pressed(int p_button) const {
 
 	_THREAD_SAFE_METHOD_
 	return (mouse_button_mask&(1<<p_button))!=0;
@@ -89,14 +89,16 @@ static int _combine_device(int p_value,int p_device) {
 	return p_value|(p_device<<20);
 }
 
-bool InputDefault::is_joy_button_pressed(int p_device, int p_button) {
+bool InputDefault::is_joy_button_pressed(int p_device, int p_button) const{
 
 	_THREAD_SAFE_METHOD_
 	return joy_buttons_pressed.has(_combine_device(p_button,p_device));
 }
 
-bool InputDefault::is_action_pressed(const StringName& p_action) {
+bool InputDefault::is_action_pressed(const StringName& p_action) const{
 
+	return action_state.has(p_action) && action_state[p_action].pressed;
+#if 0
 	if (custom_action_press.has(p_action))
 		return true; //simpler
 
@@ -147,9 +149,37 @@ bool InputDefault::is_action_pressed(const StringName& p_action) {
 	}
 
 	return false;
+#endif
 }
 
-float InputDefault::get_joy_axis(int p_device,int p_axis) {
+bool InputDefault::is_action_just_pressed(const StringName& p_action) const {
+
+	const Map<StringName,Action>::Element *E=action_state.find(p_action);
+	if (!E)
+		return false;
+
+	if (OS::get_singleton()->is_in_fixed_frame()) {
+		return E->get().pressed && E->get().fixed_frame==OS::get_singleton()->get_fixed_frames();
+	} else {
+		return E->get().pressed && E->get().idle_frame==OS::get_singleton()->get_idle_frames();
+	}
+}
+
+bool InputDefault::is_action_just_released(const StringName& p_action) const{
+
+	const Map<StringName,Action>::Element *E=action_state.find(p_action);
+	if (!E)
+		return false;
+
+	if (OS::get_singleton()->is_in_fixed_frame()) {
+		return !E->get().pressed && E->get().fixed_frame==OS::get_singleton()->get_fixed_frames();
+	} else {
+		return !E->get().pressed && E->get().idle_frame==OS::get_singleton()->get_idle_frames();
+	}
+}
+
+
+float InputDefault::get_joy_axis(int p_device,int p_axis) const{
 
 	_THREAD_SAFE_METHOD_
 	int c = _combine_device(p_axis,p_device);
@@ -247,19 +277,19 @@ void InputDefault::joy_connection_changed(int p_idx, bool p_connected, String p_
 	emit_signal("joy_connection_changed", p_idx, p_connected);
 };
 
-Vector3 InputDefault::get_accelerometer() {
+Vector3 InputDefault::get_accelerometer() const{
 
 	_THREAD_SAFE_METHOD_
 	return accelerometer;
 }
 
-Vector3 InputDefault::get_magnetometer() {
+Vector3 InputDefault::get_magnetometer() const{
 
 	_THREAD_SAFE_METHOD_
 	return magnetometer;
 }
 
-Vector3 InputDefault::get_gyroscope() {
+Vector3 InputDefault::get_gyroscope() const {
 
 	_THREAD_SAFE_METHOD_
 	return gyroscope;
@@ -341,6 +371,23 @@ void InputDefault::parse_input_event(const InputEvent& p_event) {
 
 	}
 
+
+	if (!p_event.is_echo()) {
+		for (const Map<StringName,InputMap::Action>::Element *E=InputMap::get_singleton()->get_action_map().front();E;E=E->next()) {
+
+			if (InputMap::get_singleton()->event_is_action(p_event,E->key())) {
+
+				Action action;
+				action.fixed_frame=OS::get_singleton()->get_fixed_frames();
+				action.idle_frame=OS::get_singleton()->get_idle_frames();
+				action.pressed=p_event.is_pressed();
+
+				action_state[E->key()]=action;
+
+			}
+		}
+	}
+
 	if (main_loop)
 		main_loop->input_event(p_event);
 
@@ -441,21 +488,25 @@ void InputDefault::iteration(float p_step) {
 
 void InputDefault::action_press(const StringName& p_action) {
 
-	if (custom_action_press.has(p_action)) {
+	Action action;
+
+	action.fixed_frame=OS::get_singleton()->get_fixed_frames();
+	action.idle_frame=OS::get_singleton()->get_idle_frames();
+	action.pressed=true;
+
+	action_state[p_action]=action;
 
-		custom_action_press[p_action]++;
-	} else {
-		custom_action_press[p_action]=1;
-	}
 }
 
 void InputDefault::action_release(const StringName& p_action){
 
-	ERR_FAIL_COND(!custom_action_press.has(p_action));
-	custom_action_press[p_action]--;
-	if (custom_action_press[p_action]==0) {
-		custom_action_press.erase(p_action);
-	}
+	Action action;
+
+	action.fixed_frame=OS::get_singleton()->get_fixed_frames();
+	action.idle_frame=OS::get_singleton()->get_idle_frames();
+	action.pressed=true;
+
+	action_state[p_action]=action;
 }
 
 void InputDefault::set_emulate_touch(bool p_emulate) {

+ 22 - 9
main/input_default.h

@@ -38,16 +38,27 @@ class InputDefault : public Input {
 	_THREAD_SAFE_CLASS_
 
 	int mouse_button_mask;
+
+
 	Set<int> keys_pressed;
 	Set<int> joy_buttons_pressed;
 	Map<int,float> _joy_axis;
-	Map<StringName,int> custom_action_press;
+	//Map<StringName,int> custom_action_press;
 	Vector3 accelerometer;
 	Vector3 magnetometer;
 	Vector3 gyroscope;
 	Vector2 mouse_pos;
 	MainLoop *main_loop;
 
+	struct Action {
+		uint64_t fixed_frame;
+		uint64_t idle_frame;
+		bool pressed;
+	};
+
+	Map<StringName,Action> action_state;
+
+
 	bool emulate_touch;
 
 	struct VibrationInfo {
@@ -164,12 +175,14 @@ public:
 
 
 
-	virtual bool is_key_pressed(int p_scancode);
-	virtual bool is_mouse_button_pressed(int p_button);
-	virtual bool is_joy_button_pressed(int p_device, int p_button);
-	virtual bool is_action_pressed(const StringName& p_action);
+	virtual bool is_key_pressed(int p_scancode) const;
+	virtual bool is_mouse_button_pressed(int p_button) const;
+	virtual bool is_joy_button_pressed(int p_device, int p_button) const;
+	virtual bool is_action_pressed(const StringName& p_action) const;
+	virtual bool is_action_just_pressed(const StringName& p_action) const;
+	virtual bool is_action_just_released(const StringName& p_action) const;
 
-	virtual float get_joy_axis(int p_device,int p_axis);
+	virtual float get_joy_axis(int p_device,int p_axis) const;
 	String get_joy_name(int p_idx);
 	virtual Array get_connected_joysticks();
 	virtual Vector2 get_joy_vibration_strength(int p_device);
@@ -178,9 +191,9 @@ public:
 	void joy_connection_changed(int p_idx, bool p_connected, String p_name, String p_guid = "");
 	void parse_joystick_mapping(String p_mapping, bool p_update_existing);
 
-	virtual Vector3 get_accelerometer();
-	virtual Vector3 get_magnetometer();
-	virtual Vector3 get_gyroscope();
+	virtual Vector3 get_accelerometer() const;
+	virtual Vector3 get_magnetometer() const;
+	virtual Vector3 get_gyroscope() const;
 
 	virtual Point2 get_mouse_pos() const;
 	virtual Point2 get_mouse_speed() const;

+ 6 - 0
main/main.cpp

@@ -1560,6 +1560,8 @@ bool Main::iteration() {
 
 	int iters = 0;
 
+	OS::get_singleton()->_in_fixed=true;
+
 	while(time_accum>frame_slice) {
 
 		uint64_t fixed_begin = OS::get_singleton()->get_ticks_usec();
@@ -1590,8 +1592,11 @@ bool Main::iteration() {
 		fixed_process_ticks=MAX(fixed_process_ticks,OS::get_singleton()->get_ticks_usec()-fixed_begin); // keep the largest one for reference
 		fixed_process_max=MAX(OS::get_singleton()->get_ticks_usec()-fixed_begin,fixed_process_max);
 		iters++;
+		OS::get_singleton()->_fixed_frames++;
 	}
 
+	OS::get_singleton()->_in_fixed=false;
+
 	uint64_t idle_begin = OS::get_singleton()->get_ticks_usec();
 
 	OS::get_singleton()->get_main_loop()->idle( step*time_scale );
@@ -1640,6 +1645,7 @@ bool Main::iteration() {
 
 	//	x11_delay_usec(10000);
 	frames++;
+	OS::get_singleton()->_idle_frames++;
 
 	if (frame>1000000) {
 

+ 55 - 2
modules/visual_script/visual_script_nodes.cpp

@@ -3247,13 +3247,29 @@ PropertyInfo VisualScriptInputAction::get_output_value_port_info(int p_idx) cons
 
 String VisualScriptInputAction::get_caption() const {
 
+
 	return "Action";
 }
 
 
 String VisualScriptInputAction::get_text() const {
 
-	return name;
+	switch(mode) {
+		case MODE_PRESSED: {
+			return name;
+		} break;
+		case MODE_RELEASED: {
+			return "not "+name;
+		} break;
+		case MODE_JUST_PRESSED: {
+			return String(name)+" "+TTR("just pressed");
+		} break;
+		case MODE_JUST_RELEASED: {
+			return String(name)+" "+TTR("just released");
+		} break;
+	}
+
+	return String();
 }
 
 
@@ -3278,19 +3294,50 @@ StringName VisualScriptInputAction::get_action_name() const {
 	return name;
 }
 
+void VisualScriptInputAction::set_action_mode(Mode p_mode) {
+
+	if (mode==p_mode)
+		return;
+
+	mode=p_mode;
+	ports_changed_notify();
+
+}
+VisualScriptInputAction::Mode VisualScriptInputAction::get_action_mode() const {
+
+	return mode;
+}
+
 
 class VisualScriptNodeInstanceInputAction : public VisualScriptNodeInstance {
 public:
 
 	VisualScriptInstance* instance;
 	StringName action;
+	VisualScriptInputAction::Mode mode;
 
 
 	virtual int get_working_memory_size() const { return 1; }
 
 	virtual int step(const Variant** p_inputs,Variant** p_outputs,StartMode p_start_mode,Variant* p_working_mem,Variant::CallError& r_error,String& r_error_str) {
 
-		*p_outputs[0]=Input::get_singleton()->is_action_pressed(action);
+		switch(mode) {
+			case VisualScriptInputAction::MODE_PRESSED: {
+				*p_outputs[0]=Input::get_singleton()->is_action_pressed(action);
+			} break;
+			case VisualScriptInputAction::MODE_RELEASED: {
+				*p_outputs[0]=!Input::get_singleton()->is_action_pressed(action);
+			} break;
+			case VisualScriptInputAction::MODE_JUST_PRESSED: {
+				*p_outputs[0]=Input::get_singleton()->is_action_just_pressed(action);
+			} break;
+			case VisualScriptInputAction:: MODE_JUST_RELEASED: {
+				*p_outputs[0]=Input::get_singleton()->is_action_just_released(action);
+			} break;
+
+		}
+
+
 		return 0;
 	}
 
@@ -3302,6 +3349,7 @@ VisualScriptNodeInstance* VisualScriptInputAction::instance(VisualScriptInstance
 	VisualScriptNodeInstanceInputAction * instance = memnew(VisualScriptNodeInstanceInputAction );
 	instance->instance=p_instance;
 	instance->action=name;
+	instance->mode=mode;
 
 	return instance;
 }
@@ -3348,13 +3396,18 @@ void VisualScriptInputAction::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("set_action_name","name"),&VisualScriptInputAction::set_action_name);
 	ObjectTypeDB::bind_method(_MD("get_action_name"),&VisualScriptInputAction::get_action_name);
 
+	ObjectTypeDB::bind_method(_MD("set_action_mode","mode"),&VisualScriptInputAction::set_action_mode);
+	ObjectTypeDB::bind_method(_MD("get_action_mode"),&VisualScriptInputAction::get_action_mode);
+
 	ADD_PROPERTY( PropertyInfo(Variant::STRING,"action"),_SCS("set_action_name"),_SCS("get_action_name"));
+	ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Pressed,Released,JustPressed,JustReleased"),_SCS("set_action_mode"),_SCS("get_action_mode"));
 
 }
 
 VisualScriptInputAction::VisualScriptInputAction() {
 
 	name="";
+	mode=MODE_PRESSED;
 
 }
 

+ 12 - 1
modules/visual_script/visual_script_nodes.h

@@ -906,8 +906,16 @@ public:
 class VisualScriptInputAction: public VisualScriptNode {
 
 	OBJ_TYPE(VisualScriptInputAction,VisualScriptNode)
+public:
+	enum Mode {
+		MODE_PRESSED,
+		MODE_RELEASED,
+		MODE_JUST_PRESSED,
+		MODE_JUST_RELEASED,
+	};
 
 	StringName name;
+	Mode mode;
 
 protected:
 
@@ -936,12 +944,15 @@ public:
 	void set_action_name(const StringName& p_name);
 	StringName get_action_name() const;
 
+	void set_action_mode(Mode p_mode);
+	Mode get_action_mode() const;
+
 	virtual VisualScriptNodeInstance* instance(VisualScriptInstance* p_instance);
 
 	VisualScriptInputAction();
 };
 
-
+VARIANT_ENUM_CAST( VisualScriptInputAction::Mode )
 
 class VisualScriptDeconstruct: public VisualScriptNode {