• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5'use strict';
6
7base.requireStylesheet('ui.quad_stack');
8
9base.require('base.properties');
10base.require('base.bbox2');
11base.require('base.quad');
12base.require('base.utils');
13base.require('base.raf');
14base.require('ui.quad_view');
15base.require('cc.region');
16base.require('ui.camera');
17base.require('ui.rect_view');
18
19base.exportTo('ui', function() {
20  var QuadView = ui.QuadView;
21
22  function validateQuads(quads) {
23    for (var i = 0; i < quads.length; i++) {
24      if (quads[i].stackingGroupId === undefined)
25        throw new Error('All quads must have stackingGroupIds');
26    }
27  }
28
29  /**
30   * @constructor
31   */
32  var QuadStack = ui.define('quad-stack');
33
34  QuadStack.prototype = {
35    __proto__: HTMLUnknownElement.prototype,
36
37    decorate: function() {
38      this.contentContainer_ = document.createElement('view-container');
39      this.appendChild(this.contentContainer_);
40      this.viewport_ = undefined;
41      this.worldViewportRectView_ = new ui.RectView();
42      this.quads_ = undefined;
43    },
44
45    initialize: function(unpaddedWorldRect, opt_worldViewportRect) {
46      this.viewport_ = new ui.QuadViewViewport(unpaddedWorldRect);
47
48      this.viewport_.addEventListener('change', function() {
49        this.worldViewportRectView_.viewport = this.viewport_;
50      }.bind(this));
51
52      this.worldViewportRect_ = base.Rect.FromXYWH(
53          opt_worldViewportRect.x || 0,
54          opt_worldViewportRect.y || 0,
55          opt_worldViewportRect.width,
56          opt_worldViewportRect.height
57          );
58
59      this.worldViewportRectView_.viewport = this.viewport_;
60      this.worldViewportRectView_.rect = this.worldViewportRect_;
61    },
62
63    get layers() {
64      return this.layers_;
65    },
66
67    set layers(newValue) {
68      base.setPropertyAndDispatchChange(this, 'layers', newValue);
69    },
70
71    get quads() {
72      return this.quads_;
73    },
74
75    set quads(quads) {
76      validateQuads(quads);
77      this.quads_ = quads;
78      this.updateContents_();
79    },
80
81    get viewport() {
82      return this.viewport_;
83    },
84
85    get worldViewportRect() {
86      return this.worldViewportRect_;
87    },
88
89    get worldViewportRectView() {
90      return this.worldViewportRectView_;
91    },
92
93    get contentContainer() {
94      return this.contentContainer_;
95    },
96
97    updateContents_: function() {
98      // Build the stacks.
99      var stackingGroupsById = {};
100      var quads = this.quads;
101      for (var i = 0; i < quads.length; i++) {
102        var quad = quads[i];
103        if (stackingGroupsById[quad.stackingGroupId] === undefined)
104          stackingGroupsById[quad.stackingGroupId] = [];
105        stackingGroupsById[quad.stackingGroupId].push(quad);
106      }
107
108      // Remove worldViewportRectView to re-insert after Quads.
109      if (this.worldViewportRectView_.parentNode === this.contentContainer_)
110        this.contentContainer_.removeChild(this.worldViewportRectView_);
111
112      // Get rid of old quad views if needed.
113      var numStackingGroups = base.dictionaryValues(stackingGroupsById).length;
114      while (this.contentContainer_.children.length > numStackingGroups) {
115        var n = this.contentContainer_.children.length - 1;
116        this.contentContainer_.removeChild(
117            this.contentContainer_.children[n]);
118      }
119
120      // Helper function to create a new quad view and track the current one.
121      var that = this;
122      var curQuadViewIndex = -1;
123      var curQuadView = undefined;
124      function appendNewQuadView() {
125        curQuadViewIndex++;
126        if (curQuadViewIndex < that.contentContainer_.children.length) {
127          curQuadView = that.contentContainer_.children[curQuadViewIndex];
128        } else {
129          curQuadView = new QuadView();
130          that.contentContainer_.appendChild(curQuadView);
131        }
132        curQuadView.quads = undefined;
133        curQuadView.viewport = that.viewport_;
134        curQuadView.pendingQuads = [];
135        curQuadView.region = new cc.Region();
136        return curQuadView;
137      }
138
139      appendNewQuadView();
140      for (var stackingGroupId in stackingGroupsById) {
141        var stackingGroup = stackingGroupsById[stackingGroupId];
142        var bbox = new base.BBox2();
143        stackingGroup.forEach(function(q) { bbox.addQuad(q); });
144        var bboxRect = bbox.asRect();
145
146        if (curQuadView.region.rectIntersects(bboxRect))
147          appendNewQuadView();
148        curQuadView.region.rects.push(bboxRect);
149        stackingGroup.forEach(function(q) {
150          curQuadView.pendingQuads.push(q);
151        });
152      }
153
154      // Add worldViewportRectView after the Quads.
155      this.contentContainer_.appendChild(this.worldViewportRectView_);
156
157      for (var i = 0; i < this.contentContainer_.children.length; i++) {
158        var child = this.contentContainer_.children[i];
159        if (child instanceof ui.QuadView) {
160          child.quads = child.pendingQuads;
161          delete child.pendingQuads;
162        }
163      }
164
165      this.viewport.updateBoxSize(this.contentContainer_);
166      this.layers = this.contentContainer_.children;
167    },
168
169
170  };
171
172  return {
173    QuadStack: QuadStack
174  };
175});
176