// Copyright (c) 2013 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. 'use strict'; base.requireStylesheet('ui.quad_stack'); base.require('base.properties'); base.require('base.bbox2'); base.require('base.quad'); base.require('base.utils'); base.require('base.raf'); base.require('ui.quad_view'); base.require('cc.region'); base.require('ui.camera'); base.require('ui.rect_view'); base.exportTo('ui', function() { var QuadView = ui.QuadView; function validateQuads(quads) { for (var i = 0; i < quads.length; i++) { if (quads[i].stackingGroupId === undefined) throw new Error('All quads must have stackingGroupIds'); } } /** * @constructor */ var QuadStack = ui.define('quad-stack'); QuadStack.prototype = { __proto__: HTMLUnknownElement.prototype, decorate: function() { this.contentContainer_ = document.createElement('view-container'); this.appendChild(this.contentContainer_); this.viewport_ = undefined; this.worldViewportRectView_ = new ui.RectView(); this.quads_ = undefined; }, initialize: function(unpaddedWorldRect, opt_worldViewportRect) { this.viewport_ = new ui.QuadViewViewport(unpaddedWorldRect); this.viewport_.addEventListener('change', function() { this.worldViewportRectView_.viewport = this.viewport_; }.bind(this)); this.worldViewportRect_ = base.Rect.FromXYWH( opt_worldViewportRect.x || 0, opt_worldViewportRect.y || 0, opt_worldViewportRect.width, opt_worldViewportRect.height ); this.worldViewportRectView_.viewport = this.viewport_; this.worldViewportRectView_.rect = this.worldViewportRect_; }, get layers() { return this.layers_; }, set layers(newValue) { base.setPropertyAndDispatchChange(this, 'layers', newValue); }, get quads() { return this.quads_; }, set quads(quads) { validateQuads(quads); this.quads_ = quads; this.updateContents_(); }, get viewport() { return this.viewport_; }, get worldViewportRect() { return this.worldViewportRect_; }, get worldViewportRectView() { return this.worldViewportRectView_; }, get contentContainer() { return this.contentContainer_; }, updateContents_: function() { // Build the stacks. var stackingGroupsById = {}; var quads = this.quads; for (var i = 0; i < quads.length; i++) { var quad = quads[i]; if (stackingGroupsById[quad.stackingGroupId] === undefined) stackingGroupsById[quad.stackingGroupId] = []; stackingGroupsById[quad.stackingGroupId].push(quad); } // Remove worldViewportRectView to re-insert after Quads. if (this.worldViewportRectView_.parentNode === this.contentContainer_) this.contentContainer_.removeChild(this.worldViewportRectView_); // Get rid of old quad views if needed. var numStackingGroups = base.dictionaryValues(stackingGroupsById).length; while (this.contentContainer_.children.length > numStackingGroups) { var n = this.contentContainer_.children.length - 1; this.contentContainer_.removeChild( this.contentContainer_.children[n]); } // Helper function to create a new quad view and track the current one. var that = this; var curQuadViewIndex = -1; var curQuadView = undefined; function appendNewQuadView() { curQuadViewIndex++; if (curQuadViewIndex < that.contentContainer_.children.length) { curQuadView = that.contentContainer_.children[curQuadViewIndex]; } else { curQuadView = new QuadView(); that.contentContainer_.appendChild(curQuadView); } curQuadView.quads = undefined; curQuadView.viewport = that.viewport_; curQuadView.pendingQuads = []; curQuadView.region = new cc.Region(); return curQuadView; } appendNewQuadView(); for (var stackingGroupId in stackingGroupsById) { var stackingGroup = stackingGroupsById[stackingGroupId]; var bbox = new base.BBox2(); stackingGroup.forEach(function(q) { bbox.addQuad(q); }); var bboxRect = bbox.asRect(); if (curQuadView.region.rectIntersects(bboxRect)) appendNewQuadView(); curQuadView.region.rects.push(bboxRect); stackingGroup.forEach(function(q) { curQuadView.pendingQuads.push(q); }); } // Add worldViewportRectView after the Quads. this.contentContainer_.appendChild(this.worldViewportRectView_); for (var i = 0; i < this.contentContainer_.children.length; i++) { var child = this.contentContainer_.children[i]; if (child instanceof ui.QuadView) { child.quads = child.pendingQuads; delete child.pendingQuads; } } this.viewport.updateBoxSize(this.contentContainer_); this.layers = this.contentContainer_.children; }, }; return { QuadStack: QuadStack }; });