// // Lol Engine — Input tutorial // // Copyright © 2011—2019 Sam Hocevar // // Lol Engine is free software. It comes without any warranty, to // the extent permitted by applicable law. You can redistribute it // and/or modify it under the terms of the Do What the Fuck You Want // to Public License, Version 2, as published by the WTFPL Task Force. // See http://www.wtfpl.net/ for more details. // #if HAVE_CONFIG_H # include "config.h" #endif #include #include "loldebug.h" using namespace lol; LOLFX_RESOURCE_DECLARE(07_input); class InputTutorial : public WorldEntity { public: InputTutorial() { m_pitch_angle = 0; m_yaw_angle = 0; m_autorot = true; /* Front vertices/colors */ m_mesh.push(vec3(-1.0, -1.0, 1.0), vec3(1.0, 0.0, 1.0)); m_mesh.push(vec3( 1.0, -1.0, 1.0), vec3(0.0, 1.0, 0.0)); m_mesh.push(vec3( 1.0, 1.0, 1.0), vec3(1.0, 0.5, 0.0)); m_mesh.push(vec3(-1.0, 1.0, 1.0), vec3(1.0, 1.0, 0.0)); /* Back */ m_mesh.push(vec3(-1.0, -1.0, -1.0), vec3(1.0, 0.0, 0.0)); m_mesh.push(vec3( 1.0, -1.0, -1.0), vec3(0.0, 0.5, 0.0)); m_mesh.push(vec3( 1.0, 1.0, -1.0), vec3(0.0, 0.5, 1.0)); m_mesh.push(vec3(-1.0, 1.0, -1.0), vec3(0.0, 0.0, 1.0)); m_faces_indices << 0 << 1 << 2 << 2 << 3 << 0; m_faces_indices << 1 << 5 << 6 << 6 << 2 << 1; m_faces_indices << 7 << 6 << 5 << 5 << 4 << 7; m_faces_indices << 4 << 0 << 3 << 3 << 7 << 4; m_faces_indices << 4 << 5 << 1 << 1 << 0 << 4; m_faces_indices << 3 << 2 << 6 << 6 << 7 << 3; m_lines_indices << 0 << 1 << 1 << 2 << 2 << 3 << 3 << 0; m_lines_indices << 4 << 5 << 5 << 6 << 6 << 7 << 7 << 4; m_lines_indices << 0 << 4 << 1 << 5 << 2 << 6 << 3 << 7; m_text = new Text("", "data/font/ascii.png"); m_text->SetPos(vec3(5, 30, 1)); Ticker::Ref(m_text); m_ready = false; } ~InputTutorial() { Ticker::Unref(m_text); } virtual void tick_game(float seconds) { WorldEntity::tick_game(seconds); auto mouse = input::mouse(); auto keyboard = input::keyboard(); /* Handle keyboard */ if (keyboard->key_pressed(input::key::SC_Space)) m_autorot = !m_autorot; /* Handle joystick */ auto joystick = input::joystick(0); if ((bool)joystick) { if (lol::abs(joystick->axis(input::axis::LeftY)) > 0.2f) m_pitch_angle += joystick->axis(input::axis::LeftY) * seconds; if (lol::abs(joystick->axis(input::axis::LeftX)) > 0.2f) m_yaw_angle += joystick->axis(input::axis::LeftX) * seconds; } /* Handle mouse */ if (true) { if (mouse->button(input::button::BTN_Left)) { mouse->capture(true); m_pitch_angle += mouse->axis(input::axis::MoveY) * seconds * 0.1f; m_yaw_angle += mouse->axis(input::axis::MoveX) * seconds * 0.1f; } else { mouse->capture(false); if (m_autorot) m_yaw_angle += seconds * 0.2f; } m_text->SetText(lol::format( "cursor: (%0.3f,%0.3f) - pixel (%d,%d)\n" " move: (%0.3f,%0.3f) - pixel (%d,%d)", mouse->axis(input::axis::X), mouse->axis(input::axis::Y), (int)mouse->axis(input::axis::ScreenX), (int)mouse->axis(input::axis::ScreenY), mouse->axis(input::axis::MoveX), mouse->axis(input::axis::MoveY), (int)mouse->axis(input::axis::ScreenMoveX), (int)mouse->axis(input::axis::ScreenMoveY))); } else { m_text->SetText("no mouse detected"); } mat4 anim = mat4::fromeuler_yxz(m_yaw_angle, m_pitch_angle, 0.f); mat4 model = mat4::translate(vec3(0, 0, -4.5)); mat4 view = mat4::lookat(vec3(0, 2, 0), vec3(0, 0, -4), vec3(0, 1, 0)); mat4 proj = mat4::perspective(radians(45.0f), 640.0f, 480.0f, 0.1f, 10.0f); m_matrix = proj * view * model * anim; } virtual void tick_draw(float seconds, Scene &scene) { WorldEntity::tick_draw(seconds, scene); if (!m_ready) { m_shader = Shader::Create(LOLFX_RESOURCE_NAME(07_input)); m_mvp = m_shader->GetUniformLocation("u_matrix"); m_coord = m_shader->GetAttribLocation(VertexUsage::Position, 0); m_color = m_shader->GetAttribLocation(VertexUsage::Color, 0); m_vdecl = std::make_shared( VertexStream(VertexUsage::Position, VertexUsage::Color)); m_vbo = std::make_shared(m_mesh.bytes()); void *mesh = m_vbo->Lock(0, 0); memcpy(mesh, &m_mesh[0], m_mesh.bytes()); m_vbo->Unlock(); m_lines_ibo = std::make_shared(m_lines_indices.bytes()); void *indices = m_lines_ibo->Lock(0, 0); memcpy(indices, &m_lines_indices[0], m_lines_indices.bytes()); m_lines_ibo->Unlock(); m_faces_ibo = std::make_shared(m_faces_indices.bytes()); indices = m_faces_ibo->Lock(0, 0); memcpy(indices, &m_faces_indices[0], m_faces_indices.bytes()); m_faces_ibo->Unlock(); /* FIXME: this object never cleans up */ m_ready = true; } scene.get_renderer()->SetClearColor(vec4(0.0f, 0.0f, 0.0f, 1.0f)); m_shader->Bind(); m_vdecl->SetStream(m_vbo, m_coord, m_color); m_vdecl->Bind(); m_shader->SetUniform(m_mvp, m_matrix); m_lines_ibo->Bind(); m_vdecl->DrawIndexedElements(MeshPrimitive::Lines, m_lines_indices.count()); m_lines_ibo->Unbind(); m_shader->SetUniform(m_mvp, m_matrix * mat4::scale(0.5f)); m_faces_ibo->Bind(); m_vdecl->DrawIndexedElements(MeshPrimitive::Triangles, m_faces_indices.count()); m_faces_ibo->Unbind(); m_vdecl->Unbind(); } private: bool m_autorot; float m_pitch_angle; float m_yaw_angle; mat4 m_matrix; array m_mesh; array m_lines_indices, m_faces_indices; std::shared_ptr m_shader; ShaderAttrib m_coord, m_color; ShaderUniform m_mvp; std::shared_ptr m_vdecl; std::shared_ptr m_vbo; std::shared_ptr m_lines_ibo, m_faces_ibo; Text *m_text; bool m_ready; }; int main(int argc, char **argv) { sys::init(argc, argv); Application app("Tutorial 7: Input", ivec2(640, 480), 60.0f); new DebugFps(5, 5); new InputTutorial(); app.Run(); return EXIT_SUCCESS; }