summaryrefslogtreecommitdiffstats
path: root/native_client_sdk/src/examples/tumbler/tumbler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'native_client_sdk/src/examples/tumbler/tumbler.cc')
-rw-r--r--native_client_sdk/src/examples/tumbler/tumbler.cc137
1 files changed, 137 insertions, 0 deletions
diff --git a/native_client_sdk/src/examples/tumbler/tumbler.cc b/native_client_sdk/src/examples/tumbler/tumbler.cc
new file mode 100644
index 0000000..57343c4
--- /dev/null
+++ b/native_client_sdk/src/examples/tumbler/tumbler.cc
@@ -0,0 +1,137 @@
+// Copyright (c) 2011 The Native Client 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 "examples/tumbler/tumbler.h"
+
+#include <cstdlib>
+#include <cstring>
+#include <string>
+#include <vector>
+
+#include "examples/tumbler/cube.h"
+#include "examples/tumbler/opengl_context.h"
+#include "examples/tumbler/scripting_bridge.h"
+#include "ppapi/cpp/rect.h"
+#include "ppapi/cpp/size.h"
+#include "ppapi/cpp/var.h"
+
+namespace {
+const size_t kQuaternionElementCount = 4;
+const char* const kArrayStartCharacter = "[";
+const char* const kArrayEndCharacter = "]";
+const char* const kArrayDelimiter = ",";
+
+// Return the value of parameter named |param_name| from |parameters|. If
+// |param_name| doesn't exist, then return an empty string.
+std::string GetParameterNamed(
+ const std::string& param_name,
+ const tumbler::MethodParameter& parameters) {
+ tumbler::MethodParameter::const_iterator i =
+ parameters.find(param_name);
+ if (i == parameters.end()) {
+ return "";
+ }
+ return i->second;
+}
+
+// Convert the JSON string |array| into a vector of floats. |array| is
+// expected to be a string bounded by '[' and ']', and a comma-delimited list
+// of numbers. Any errors result in the return of an empty array.
+std::vector<float> CreateArrayFromJSON(const std::string& json_array) {
+ std::vector<float> float_array;
+ size_t array_start_pos = json_array.find_first_of(kArrayStartCharacter);
+ size_t array_end_pos = json_array.find_last_of(kArrayEndCharacter);
+ if (array_start_pos == std::string::npos ||
+ array_end_pos == std::string::npos)
+ return float_array; // Malformed JSON: missing '[' or ']'.
+ // Pull out the array elements.
+ size_t token_pos = array_start_pos + 1;
+ while (token_pos < array_end_pos) {
+ float_array.push_back(strtof(json_array.data() + token_pos, NULL));
+ size_t delim_pos = json_array.find_first_of(kArrayDelimiter, token_pos);
+ if (delim_pos == std::string::npos)
+ break;
+ token_pos = delim_pos + 1;
+ }
+ return float_array;
+}
+} // namespace
+
+namespace tumbler {
+
+Tumbler::Tumbler(PP_Instance instance)
+ : pp::Instance(instance),
+ cube_(NULL) {
+}
+
+Tumbler::~Tumbler() {
+ // Destroy the cube view while GL context is current.
+ opengl_context_->MakeContextCurrent(this);
+ delete cube_;
+}
+
+bool Tumbler::Init(uint32_t /* argc */,
+ const char* /* argn */[],
+ const char* /* argv */[]) {
+ // Add all the methods to the scripting bridge.
+ ScriptingBridge::SharedMethodCallbackExecutor set_orientation_method(
+ new tumbler::MethodCallback<Tumbler>(
+ this, &Tumbler::SetCameraOrientation));
+ scripting_bridge_.AddMethodNamed("setCameraOrientation",
+ set_orientation_method);
+ return true;
+}
+
+void Tumbler::HandleMessage(const pp::Var& message) {
+ if (!message.is_string())
+ return;
+ scripting_bridge_.InvokeMethod(message.AsString());
+}
+
+void Tumbler::DidChangeView(const pp::Rect& position, const pp::Rect& clip) {
+ int cube_width = cube_ ? cube_->width() : 0;
+ int cube_height = cube_ ? cube_->height() : 0;
+ if (position.size().width() == cube_width &&
+ position.size().height() == cube_height)
+ return; // Size didn't change, no need to update anything.
+
+ if (opengl_context_ == NULL)
+ opengl_context_.reset(new OpenGLContext(this));
+ opengl_context_->InvalidateContext(this);
+ opengl_context_->ResizeContext(position.size());
+ if (!opengl_context_->MakeContextCurrent(this))
+ return;
+ if (cube_ == NULL) {
+ cube_ = new Cube(opengl_context_);
+ cube_->PrepareOpenGL();
+ }
+ cube_->Resize(position.size().width(), position.size().height());
+ DrawSelf();
+}
+
+void Tumbler::DrawSelf() {
+ if (cube_ == NULL || opengl_context_ == NULL)
+ return;
+ opengl_context_->MakeContextCurrent(this);
+ cube_->Draw();
+ opengl_context_->FlushContext();
+}
+
+void Tumbler::SetCameraOrientation(
+ const tumbler::ScriptingBridge& bridge,
+ const tumbler::MethodParameter& parameters) {
+ // |parameters| is expected to contain one object named "orientation", whose
+ // value is a JSON string that represents an array of four floats.
+ if (parameters.size() != 1 || cube_ == NULL)
+ return;
+ std::string orientation_desc = GetParameterNamed("orientation", parameters);
+ std::vector<float> orientation = CreateArrayFromJSON(orientation_desc);
+ if (orientation.size() != kQuaternionElementCount) {
+ return;
+ }
+ cube_->SetOrientation(orientation);
+ DrawSelf();
+}
+} // namespace tumbler
+