// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include <algorithm> #include <cmath> #include <stdarg.h> #include <stdio.h> #include "ppapi/c/ppb_gamepad.h" #include "ppapi/c/ppb_input_event.h" #include "ppapi/cpp/completion_callback.h" #include "ppapi/cpp/graphics_2d.h" #include "ppapi/cpp/image_data.h" #include "ppapi/cpp/input_event.h" #include "ppapi/cpp/instance.h" #include "ppapi/cpp/logging.h" #include "ppapi/cpp/module.h" #include "ppapi/cpp/rect.h" #include "ppapi/cpp/var.h" #include "ppapi/cpp/view.h" #include "ppapi/utility/completion_callback_factory.h" void FillRect(pp::ImageData* image, int left, int top, int width, int height, uint32_t color) { for (int y = std::max(0, top); y < std::min(image->size().height() - 1, top + height); y++) { for (int x = std::max(0, left); x < std::min(image->size().width() - 1, left + width); x++) *image->GetAddr32(pp::Point(x, y)) = color; } } class MyInstance : public pp::Instance { public: explicit MyInstance(PP_Instance instance) : pp::Instance(instance), width_(0), height_(0), callback_factory_(this), gamepad_(NULL) { } virtual ~MyInstance() {} virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) { gamepad_ = reinterpret_cast<const PPB_Gamepad*>( pp::Module::Get()->GetBrowserInterface(PPB_GAMEPAD_INTERFACE)); if (!gamepad_) return false; return true; } virtual void DidChangeView(const pp::View& view) { pp::Rect rect = view.GetRect(); if (rect.size().width() == width_ && rect.size().height() == height_) return; // We don't care about the position, only the size. width_ = rect.size().width(); height_ = rect.size().height(); device_context_ = pp::Graphics2D(this, pp::Size(width_, height_), false); if (!BindGraphics(device_context_)) return; Paint(); } void OnFlush(int32_t) { Paint(); } private: void Paint() { pp::ImageData image = PaintImage(device_context_.size()); if (!image.is_null()) { device_context_.ReplaceContents(&image); device_context_.Flush( callback_factory_.NewCallback(&MyInstance::OnFlush)); } else { printf("NullImage\n"); } } pp::ImageData PaintImage(const pp::Size& size) { pp::ImageData image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL, size, true); if (image.is_null()) return image; PP_GamepadsSampleData gamepad_data; gamepad_->Sample(pp_instance(), &gamepad_data); if (gamepad_data.length > 1 && gamepad_data.items[0].connected) { int width2 = size.width() / 2; int height2 = size.height() / 2; // Draw 2 axes for (size_t i = 0; i < gamepad_data.items[0].axes_length; i += 2) { int x = static_cast<int>( gamepad_data.items[0].axes[i + 0] * width2 + width2); int y = static_cast<int>( gamepad_data.items[0].axes[i + 1] * height2 + height2); uint32_t box_bgra = 0x80000000; // Alpha 50%. FillRect(&image, x - 3, y - 3, 7, 7, box_bgra); } for (size_t i = 0; i < gamepad_data.items[0].buttons_length; ++i) { float button_val = gamepad_data.items[0].buttons[i]; uint32_t colour = static_cast<uint32_t>((button_val * 192) + 63) << 24; int x = i * 8 + 10; int y = 10; FillRect(&image, x - 3, y - 3, 7, 7, colour); } } return image; } int width_; int height_; pp::CompletionCallbackFactory<MyInstance> callback_factory_; const PPB_Gamepad* gamepad_; pp::Graphics2D device_context_; }; // This object is the global object representing this plugin library as long // as it is loaded. class MyModule : public pp::Module { public: MyModule() : pp::Module() {} virtual ~MyModule() {} // Override CreateInstance to create your customized Instance object. virtual pp::Instance* CreateInstance(PP_Instance instance) { return new MyInstance(instance); } }; namespace pp { // Factory function for your specialization of the Module object. Module* CreateModule() { return new MyModule(); } } // namespace pp