blob: 17b1341de98d7bade8dbeaa6d7e06b7c3f7d01bd [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_UI_LIB_ESCHER_SCENE_OBJECT_H_
#define SRC_UI_LIB_ESCHER_SCENE_OBJECT_H_
#include <unordered_map>
#include "src/ui/lib/escher/geometry/transform.h"
#include "src/ui/lib/escher/material/material.h"
#include "src/ui/lib/escher/scene/shape.h"
namespace escher {
// An object instance to be drawn using a shape and a material.
// Does not retain ownership of the material.
class Object {
public:
// Constructors.
Object(const Transform& transform, MeshPtr mesh, MaterialPtr material);
Object(const mat4& transform, MeshPtr mesh, MaterialPtr material);
Object(const vec3& position, MeshPtr mesh, MaterialPtr material);
Object(std::vector<Object> clippers, std::vector<Object> clippees);
Object(const Object& other) = default;
Object(Object&& other) = default;
static Object NewRect(const vec2& top_left_position, const vec2& size, float z,
MaterialPtr material);
static Object NewRect(const vec3& top_left_position, const vec2& size, MaterialPtr material);
static Object NewRect(const Transform& transform, MaterialPtr material);
static Object NewRect(const mat4& transform, MaterialPtr material);
static Object NewCircle(const vec2& center_position, float radius, float z, MaterialPtr material);
static Object NewCircle(const vec3& center_position, float radius, MaterialPtr material);
static Object NewCircle(const mat4& transform, float radius, MaterialPtr material);
// Return the object's 4x4 transformation matrix.
const mat4& transform() const { return transform_; }
// The shape to draw.
const Shape& shape() const { return shape_; }
Shape& mutable_shape() { return shape_; }
// The material with which to fill the shape.
const MaterialPtr& material() const { return material_; }
void set_material(MaterialPtr material) { material_ = std::move(material); }
// Return the bounding box that encompasses the object's shape, as well as
// all of its clippers (but not clippees, since their clipped bounds are
// by definition within the clippers' bounds).
BoundingBox bounding_box() const;
Object& set_shape_modifiers(ShapeModifiers modifiers) {
shape_.set_modifiers(modifiers);
return *this;
}
// Obtain a temporary reference to data corresponding to a particular
// ShapeModifier; the modifier that is used is determined by DataT::kType.
// The returned pointer is invalidated by the next call to
// set_shape_modifier_data(). Escher clients should only use pre-existing
// Escher types for DataT (e.g. ModifierWobble), since those are the ones that
// the renderer implementation knows how to deal with.
template <typename DataT>
const DataT* shape_modifier_data() const;
// Set per-object ShapeModifier data for the ShapeModifier type specified by
// DataT::kType. Uses memcpy() to copy the DataT into shape_modifier_data_.
template <typename DataT>
void set_shape_modifier_data(const DataT& data);
// Remove both the shape modifier data and the flag from the shape.
template <typename DataT>
void remove_shape_modifier();
// Return the list of objects whose shapes will be used to clip 'clippees()'.
// It is OK for these objects to not have a material; in this case the objects
// update the stencil buffer, but not the color/depth buffers.
const std::vector<Object>& clippers() const { return clippers_; }
// Return the list of objects whose shapes will be clipped by 'clippers()'.
const std::vector<Object>& clippees() const { return clippees_; }
private:
Object(mat4 transform, Shape shape, MaterialPtr material)
: transform_(transform), shape_(std::move(shape)), material_(std::move(material)) {}
mat4 transform_;
Shape shape_;
MaterialPtr material_;
std::unordered_map<ShapeModifier, std::vector<uint8_t>> shape_modifier_data_;
std::vector<Object> clippers_;
std::vector<Object> clippees_;
};
// Inline function definitions.
template <typename DataT>
const DataT* Object::shape_modifier_data() const {
auto it = shape_modifier_data_.find(DataT::kType);
if (it == shape_modifier_data_.end()) {
return nullptr;
} else {
FXL_DCHECK(it->second.size() == sizeof(DataT));
return reinterpret_cast<const DataT*>(it->second.data());
}
}
template <typename DataT>
void Object::set_shape_modifier_data(const DataT& data) {
auto& vect = shape_modifier_data_[DataT::kType];
vect.resize(sizeof(DataT));
memcpy(vect.data(), &data, sizeof(DataT));
}
template <typename DataT>
void Object::remove_shape_modifier() {
shape_modifier_data_.erase(DataT::kType);
shape_.remove_modifier(DataT::kType);
}
template <typename DataT>
void set_shape_modifier_data(const DataT& data);
} // namespace escher
#endif // SRC_UI_LIB_ESCHER_SCENE_OBJECT_H_