static void UpdateCamera(fplbase::InputSystem* input, Camera* camera) { const fplbase::InputPointer& pointer = input->get_pointers()[0]; if (!pointer.used) return; // Update latitude and longitude: left mouse drag. if (input->GetButton(fplbase::K_POINTER1).is_down() && pointer.mousedelta != mathfu::kZeros2i) { const float lat = camera->latitude.ToRadians() + pointer.mousedelta.y * kLatitudeSensitivity; camera->latitude = Angle(mathfu::Clamp(lat, -kMaxLatitude, kMaxLatitude)); camera->longitude += Angle(pointer.mousedelta.x * kLongitudeSensitivity); } // Update distance: right mouse drag. // (Unfortunately, InputSystem doesn't support scroll wheels yet) if (input->GetButton(fplbase::K_POINTER3).is_down() && pointer.mousedelta != mathfu::kZeros2i) { const float dist = camera->distance + (pointer.mousedelta.x + pointer.mousedelta.y) * kDistanceSensitivity; camera->distance = std::max(dist, camera->z_near); } // Update target: middle mouse drag. if (input->GetButton(fplbase::K_POINTER2).is_down() && pointer.mousedelta != mathfu::kZeros2i) { const vec3 right = CameraRight(*camera); const vec3 up = VectorSystemUp(camera->coordinate_system); const vec2 dist = kTargetSensitivity * vec2(pointer.mousedelta); camera->target += dist[0] * right + dist[1] * up; } }
int main() { //! [Own Processor Register] LinearInit::Register(); //! [Own Processor Register] MotiveEngine engine; //! [Own Processor Create Instance] // Move from 10 --> -5 in 100 internal time units. const MotiveTarget1f target = motive::CurrentToTarget1f(10, 0, -5, 0, 100); // Create the one dimensional motivator of type Linear by passing in // LinearInit. Motivator1f linear_motivator(LinearInit(), &engine, target); //! [Own Processor Create Instance] //! [Own Processor Advance Simulation] // Advance the simulation one tick at a time by calling engine.AdvanceFrame(). std::vector<vec2> points; points.reserve(target.EndTime() + 1); for (MotiveTime t = 0; t <= target.EndTime(); ++t) { points.push_back(vec2(static_cast<float>(t), linear_motivator.Value())); engine.AdvanceFrame(1); } printf("\n%s", motive::Graph2DPoints(&points[0], static_cast<int>(points.size())) .c_str()); //! [Own Processor Advance Simulation] return 0; }
int main() { // Since we use the ‘smooth’ animation algorithm, we must register it. motive::SmoothInit::Register(); // The engine is the central place for animation data. motive::MotiveEngine engine; // In this example, we animate a one-dimensional floating point value. motive::Motivator1f facing_angle; // Initialize facing_angle Motivator to animate as a 'Smooth' Motivator. // Alternatively, we could initialize as an 'Overshoot' Motivator. All // Motivator types have the same interface. Internally, they are animated // with different algorithms, and they will move differently towards their // targets. However, to switch between Motivator types it is a simple matter // of initializing with a different kind of MotiveInit struct. // // Angles wrap around with modular arithmetic. That is, -pi is equivalent to // pi. Valid range for angles is -pi..pi, inclusive of +pi and exclusive of // -pi. const motive::SmoothInit init(Range(-kPi, kPi), true); facing_angle.Initialize(init, &engine); // Set initial state of the Motivator, and the target parameters. // 'Smooth' Motivators animate to a target-value in a target-time. Not all // types of Motivators use all target data. const Angle start = Angle::FromDegrees(120.0f); const float start_angular_velocity = 0.0f; const Angle target = Angle::FromDegrees(-120.0f); const float target_angular_velocity = 0.0f; const motive::MotiveTime target_time = 100; const motive::MotiveTime delta_time = 1; facing_angle.SetTarget( motive::CurrentToTarget1f(start.ToRadians(), start_angular_velocity, target.ToRadians(), target_angular_velocity, target_time)); std::vector<vec2> points(target_time / delta_time + 1); for (motive::MotiveTime t = 0; t <= target_time; t += delta_time) { // All Motivators created with 'engine' are animated here. engine.AdvanceFrame(delta_time); // The current value of the variable being animated is always available. const Angle angle_at_t = Angle::FromWithinThreePi(facing_angle.Value()); points.push_back( vec2(static_cast<float>(t), angle_at_t.ToDegrees())); } printf("\n%s", Graph2DPoints(&points[0], points.size()).c_str()); return 0; }
extern "C" int FPL_main(int /*argc*/, char **argv) { fplbase::Renderer renderer; renderer.Initialize(vec2i(800, 600), "FlatUI sample"); fplbase::InputSystem input; input.Initialize(); // Set the local directory to the assets folder for this sample. bool result = fplbase::ChangeToUpstreamDir(argv[0], "sample/assets"); assert(result); fplbase::AssetManager assetman(renderer); flatui::FontManager fontman; fontman.SetRenderer(renderer); // Open OpenType font. fontman.Open("fonts/NotoSansCJKjp-Bold.otf"); // Load textures. auto tex_about = assetman.LoadTexture("textures/text_about.webp"); assetman.StartLoadingTextures(); // While an initialization of flatui, it implicitly loads shaders used in the // API below using AssetManager. // shaders/color.glslv & .glslf, shaders/font.glslv & .glslf // shaders/textured.glslv & .glslf // Wait for everything to finish loading... while (assetman.TryFinalize() == false) { renderer.AdvanceFrame(input.minimized(), input.Time()); } while (!(input.exit_requested() || input.GetButton(fplbase::FPLK_AC_BACK).went_down())) { input.AdvanceFrame(&renderer.window_size()); renderer.AdvanceFrame(input.minimized(), input.Time()); const float kColorGray = 0.5f; renderer.ClearFrameBuffer( vec4(kColorGray, kColorGray, kColorGray, 1.0f)); // Show test GUI using flatui API. // In this sample, it shows basic UI elements of a label and an image. // Define flatui block. Note that the block is executed multiple times, // One for a layout pass and another for a rendering pass. Run(assetman, fontman, input, [&]() { // Set a virtual resolution all coordinates will use. 1000 is now the // size of the smallest dimension (Y in landscape mode). SetVirtualResolution(1000); // Start our root group. StartGroup(flatui::kLayoutVerticalLeft); // Position group in the center of the screen. PositionGroup(flatui::kAlignCenter, flatui::kAlignCenter, mathfu::kZeros2f); // Show a label with a font size of 40px in a virtual resotuion. Label("The quick brown fox jumps over the lazy dog.", 40); // Show an image with a virtical size of 60px in a virtual resotuion. // A width is automatically derived from the image size. Image(*tex_about, 60); EndGroup(); }); } return 0; }
int main() { // Since we will be using the ‘smooth’ animation algorithm, we must register it // with the engine. motive::SmoothInit::Register(); // The engine is the central place where animation data is stored and processed. motive::MotiveEngine engine; // In this example, we animate a one-dimensional floating point value. // It's also possible to animate a mathfu::vec2 with motive::Motivator2f, and // similarly for higher dimensional vectors. We can even animate a mathfu::mat4 // (a 4x4 matrix) with motive::MotivatorMatrix4f. // // If you have your own math library, you can also animate those instead of // mathfu types. See [Using Your Own Math Types][]. motive::Motivator1f facing_angle; // Initialize facing_angle Motivator to animate as a 'Smooth' Motivator. // Alternatively, we could initialize as an 'Overshoot' Motivator. All // Motivator types have the same interface. Internally, they are animated // with different algorithms, and they will move differently towards their // targets. However, to switch between Motivator types it is a simple matter // of initializing with a different kind of MotiveInit struct. // // Angles wrap around with modular arithmetic. That is, -pi is equivalent to // pi. Valid range for angles is -pi..pi, inclusive of +pi and exclusive of // -pi. const motive::SmoothInit init(Range(-kPi, kPi), true); facing_angle.Initialize(init, &engine); // Set initial state of the Motivator, and the target parameters. // 'Smooth' Motivators animate to a target-value in a target-time. Not all // types of Motivators use all target data. const Angle start = Angle::FromDegrees(120.0f); const float start_angular_velocity = 0.0f; const Angle target = Angle::FromDegrees(-120.0f); const float target_angular_velocity = 0.0f; const motive::MotiveTime target_time = 100; const motive::MotiveTime delta_time = 1; facing_angle.SetTarget( motive::CurrentToTarget1f(start.ToRadians(), start_angular_velocity, target.ToRadians(), target_angular_velocity, target_time)); std::vector<vec2> points(target_time / delta_time + 1); for (motive::MotiveTime t = 0; t <= target_time; t += delta_time) { // That is, all Motivators created with 'engine' are animated here. engine.AdvanceFrame(delta_time); // The current value of the variable being animated is always available. // Additionally, we can also access facing_angle.Velocity() for the angular // velocity. const Angle facing_angle_at_time_t(facing_angle.Value()); points.push_back( vec2(static_cast<float>(t), facing_angle_at_time_t.ToDegrees())); } printf("\n%s", Graph2DPoints(&points[0], points.size()).c_str()); return 0; }