Пример #1
0
void GraphicsObjectData::render(const GraphicsObject& go,
                                const GraphicsObject* parent,
                                std::ostream* tree) {
  boost::shared_ptr<const Surface> surface = currentSurface(go);
  if (surface) {
    Rect src = srcRect(go);
    Rect dst = dstRect(go, parent);
    int alpha = getRenderingAlpha(go, parent);

    if (go.buttonUsingOverides()) {
      // Tacked on side channel that lets a ButtonObjectSelectLongOperation
      // tweak the x/y coordinates of dst. There isn't really a better place to
      // put this. It can't go in dstRect() because the LongOperation also
      // consults the data from dstRect().
      dst = Rect(dst.origin() + Size(go.buttonXOffsetOverride(),
                                     go.buttonYOffsetOverride()),
                 dst.size());
    }

    if (tree) {
      objectInfo(*tree);
      *tree << "  Rendering " << src << " to " << dst << endl;
      if (parent) {
        *tree << "  Parent: ";
        PrintGraphicsObjectToTree(*parent, tree);
        *tree << endl;
      }

      *tree << "  Properties: ";
      if (alpha != 255)
        *tree << "(alpha=" << alpha << ") ";
      PrintGraphicsObjectToTree(go, tree);
      *tree << endl;
    }

    if (parent && parent->hasOwnClip()) {
      // In Little Busters, a parent clip rect is used to clip text scrolling
      // in the battle system. rlvm has the concept of parent objects badly
      // hacked in, and that means we can't directly apply the own clip
      // rect. Instead we have to calculate this in terms of the screen
      // coordinates and then apply that as a global clip rect.
      Point parent_start(parent->x() + parent->xAdjustmentSum(),
                         parent->y() + parent->yAdjustmentSum());
      Rect full_parent_clip =
          Rect(parent_start + parent->ownClipRect().origin(),
               parent->ownClipRect().size());

      Rect clipped_dest = dst.intersection(full_parent_clip);
      Rect inset = dst.getInsetRectangle(clipped_dest);
      dst = clipped_dest;
      src = src.applyInset(inset);

      if (tree) {
        *tree << "  Parent Own Clipping Rect: " << parent->ownClipRect()
              << endl
              << "  After clipping: " << src << " to " << dst << endl;
      }
    }

    if (go.hasOwnClip()) {
      dst = dst.applyInset(go.ownClipRect());
      src = src.applyInset(go.ownClipRect());

      if (tree) {
        *tree << "  Internal Clipping Rect: " << go.ownClipRect() << endl
              << "  After internal clipping: " << src << " to " << dst
              << endl;
      }
    }

    // Perform the object clipping.
    if (go.hasClip()) {
      Rect clipped_dest = dst.intersection(go.clipRect());

      // Do nothing if object falls wholly outside clip area
      if (clipped_dest.isEmpty())
        return;

      // Adjust the source rectangle
      Rect inset = dst.getInsetRectangle(clipped_dest);

      dst = clipped_dest;
      src = src.applyInset(inset);

      if (tree) {
        *tree << "  Clipping Rect: " << go.clipRect() << endl
              << "  After clipping: " << src << " to " << dst << endl;
      }
    }

    // TODO: Do we want to skip this if no alpha?
    surface->renderToScreenAsObject(go, src, dst, alpha);
  }
}