note
	description: "[
		chocolate doom doomkeys.h
		
		Key definitions
	]"
	license: "[
		Copyright (C) 1993-1996 by id Software, Inc.
		Copyright (C) 2005-2014 Simon Howard
		Copyright (C) 2021 Ilgiz Mustafin
		
		This program is free software; you can redistribute it and/or modify
		it under the terms of the GNU General Public License as published by
		the Free Software Foundation; either version 2 of the License, or
		(at your option) any later version.
		
		This program is distributed in the hope that it will be useful,
		but WITHOUT ANY WARRANTY; without even the implied warranty of
		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
		GNU General Public License for more details.
		
		You should have received a copy of the GNU General Public License along
		with this program; if not, write to the Free Software Foundation, Inc.,
		51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
	]"

class 
	I_INPUT

inherit
	DOOMKEYS_H

	SDL_SCANCODE_ENUM_API

create 
	make

feature 

	i_main: I_MAIN

	make (a_i_main: like i_main)
		do
			i_main := a_i_main
		end
	
feature 

	i_handlekeyboardevent (sdlevent: SDL_EVENT_UNION_API)
		local
			event: EVENT_T
		do
			create event.make
			if sdlevent.type = {SDL_CONSTANT_API}.sdl_keydown then
				event.type := {EVENT_T}.ev_keydown
				event.data1 := translatekey (sdlevent.key.keysym)
				event.data2 := getlocalizedkey (sdlevent.key.keysym)
				event.data3 := gettypedchar (sdlevent.key.keysym)
				if event.data1 /= 0 then
					i_main.D_main.d_postevent (event)
				end
			elseif sdlevent.type = {SDL_CONSTANT_API}.sdl_keyup then
				event.type := {EVENT_T}.ev_keyup
				event.data1 := translatekey (sdlevent.key.keysym)
				event.data2 := 0
				event.data3 := 0
				if event.data1 /= 0 then
					i_main.D_main.d_postevent (event)
				end
			end
		end

	translatekey (key: SDL_KEYSYM_STRUCT_API): INTEGER_32
			-- Translates the SDL key to a value of the type found in doomkeys.h
		local
			sc: INTEGER_32
		do
			sc := key.scancode
			if sc = sdl_scancode_lctrl or sc = sdl_scancode_rctrl then
				Result := Key_rctrl
			elseif sc = sdl_scancode_lshift or sc = sdl_scancode_rshift then
				Result := Key_rshift
			elseif sc = sdl_scancode_lalt then
				Result := Key_lalt
			elseif sc = sdl_scancode_ralt then
				Result := Key_ralt
			else
				if sc > 0 and sc <= Scancode_to_keys_array.upper then
					Result := Scancode_to_keys_array [sc]
				else
					Result := 0
				end
			end
		ensure
			instance_free: class
		end

	getlocalizedkey (key: SDL_KEYSYM_STRUCT_API): INTEGER_32
		do
			{NOT_IMPLEMENTED}.not_implemented ("GetLocalizedKey", False)
		end

	gettypedchar (key: SDL_KEYSYM_STRUCT_API): INTEGER_32
		do
			{NOT_IMPLEMENTED}.not_implemented ("GetTypedChar", False)
		end
	
feature 

	i_handlemouseevent (sdlevent: SDL_EVENT_UNION_API)
		do
			if sdlevent.type = {SDL_CONSTANT_API}.sdl_mousebuttondown then
				updatemousebuttonstate (sdlevent.button.button.natural_32_code, True)
			elseif sdlevent.type = {SDL_CONSTANT_API}.sdl_mousebuttonup then
				updatemousebuttonstate (sdlevent.button.button.natural_32_code, False)
			elseif sdlevent.type = {SDL_CONSTANT_API}.sdl_mousewheel then
				mapmousewheeltobuttons (sdlevent.wheel)
			end
		end

	Max_mouse_buttons: INTEGER_32 = 8

	mouse_button_state: NATURAL_32

	updatemousebuttonstate (a_button: NATURAL_32; on: BOOLEAN)
		local
			event: EVENT_T
			button: NATURAL_32
		do
			button := a_button
			if button.to_integer_64 < {SDL_CONSTANT_API}.sdl_button_left or button > Max_mouse_buttons.to_natural_32 then
			else
				if button.to_integer_64 = {SDL_CONSTANT_API}.sdl_button_left then
					button := 0
				elseif button.to_integer_64 = {SDL_CONSTANT_API}.sdl_button_right then
					button := 1
				elseif button.to_integer_64 = {SDL_CONSTANT_API}.sdl_button_middle then
					button := 2
				else
					button := button - 1
				end
				if on then
					mouse_button_state := mouse_button_state | ({NATURAL_32} 1 |<< button.to_integer_32)
				else
					mouse_button_state := mouse_button_state & ({NATURAL_32} 1 |<< button.to_integer_32).bit_not
				end
				create event.make
				event.type := {EVENT_T}.ev_mouse
				event.data1 := mouse_button_state.as_integer_32
				event.data2 := 0
				event.data3 := 0
				i_main.D_main.d_postevent (event)
			end
		end

	mapmousewheeltobuttons (wheel: SDL_MOUSE_WHEEL_EVENT_STRUCT_API)
		local
			up, down: EVENT_T
			button: INTEGER_32
		do
			if wheel.y <= 0 then
				button := 4
			else
				button := 3
			end
			create down.make
			mouse_button_state := mouse_button_state | ({NATURAL_32} 1 |<< button)
			down.type := {EVENT_T}.ev_mouse
			down.data1 := mouse_button_state.as_integer_32
			down.data2 := 0
			down.data3 := 0
			i_main.D_main.d_postevent (down)
			create up.make
			mouse_button_state := mouse_button_state & ({NATURAL_32} 1 |<< button).bit_not
			up.type := {EVENT_T}.ev_mouse
			up.data1 := mouse_button_state.as_integer_32
			up.data2 := 0
			up.data3 := 0
			i_main.D_main.d_postevent (up)
		end

	i_readmouse
			-- Read the change in mouse state to generate mouse motion events
			--
			-- This is to combine all mouse movement for a tic into one mouse
			-- motion event.
		local
			x, y: INTEGER_32
			ev: EVENT_T
		do
			{SDL_MOUSE_FUNCTIONS_API}.sdl_get_relative_mouse_state ($x, $y).do_nothing
			if x /= 0 and y /= 0 then
				create ev.make
				ev.type := {EVENT_T}.ev_mouse
				ev.data1 := mouse_button_state.as_integer_32
				ev.data2 := acceleratemouse (x)
				if not novert.to_boolean then
					ev.data3 := - acceleratemouse (y)
				else
					ev.data3 := 0
				end
				i_main.D_main.d_postevent (ev)
			end
		end

	mouse_acceleration: REAL_32 assign set_mouse_acceleration

	set_mouse_acceleration (a_mouse_acceleration: like mouse_acceleration)
		do
			mouse_acceleration := a_mouse_acceleration
		end

	Mouse_threshold: INTEGER_32 = 10
			-- Disallow mouse and joystick movement to cause forward/backward
			-- motion.  Specified with the '-novert' command line parameter.
			-- This is an int to allow saving to config file

	novert: INTEGER_32 assign set_novert

	set_novert (a_novert: like novert)
		do
			novert := a_novert
		end

	acceleratemouse (val: INTEGER_32): INTEGER_32
		do
			if val < 0 then
				Result := - acceleratemouse (- val)
			elseif val > Mouse_threshold then
				Result := ((val - Mouse_threshold).to_real * mouse_acceleration + Mouse_threshold.to_real).floor
			else
				Result := val
			end
		end
	
end -- class I_INPUT

Generated by ISE EiffelStudio