merge with master
diff --git a/extension/css/compsSelection.css b/extension/css/compsSelection.css
index c62efc5..9099f2e 100644
--- a/extension/css/compsSelection.css
+++ b/extension/css/compsSelection.css
@@ -170,4 +170,17 @@
     border-bottom: 1px solid red;
     padding: 4px;
 }
-    
+
+#compsSelection .settingsSeparator{
+    border-bottom: 1px solid red;
+    padding: 4px;
+}
+
+#compsSelection .extraCompositions .extraCompElement{
+    width: 100%;
+}
+
+#compsSelection .extraCompositions .extraCompElement.selected {
+    background-color: #D23641;
+    color: #EAD3A8;
+}
diff --git a/extension/index.html b/extension/index.html
index a584ff7..29ad525 100644
--- a/extension/index.html
+++ b/extension/index.html
@@ -90,6 +90,24 @@
                         </div>
                         <div class='settingsSeparator'></div>
                     </div>
+                    <div class='extraComps'>
+                        <div class='checkboxCombo'>
+                            <div class='checkbox'>
+                                <div class='circle'></div>
+                            </div>
+                            <div class='checkboxLabel'>Extra Comps (Check if expressions are pointing to external comps)</div>
+                        </div>
+                        <div class="extraCompositions">
+                            <table>
+                                <thead>
+                                </thead>
+                                <tbody>
+
+                                </tbody>
+                            </table>
+                        </div>
+                        <div class='settingsSeparator'></div>
+                    </div>
                     <div class='standalone'>
                         <div class='checkboxCombo'>
                             <div class='checkbox'>
@@ -187,7 +205,7 @@
         </div>
     </div>
     
-    <svg width='10000' height='10000' style='position:absolute;bottom:0;left:-10000px' preserveAspectRatio='meet xMidYMid' viewBox='0 0 10000 10000'>
+    <svg width='10000' height='10000' style='position:absolute;bottom:0;left:-10000px' preserveAspectRatio='xMidYMid meet' viewBox='0 0 10000 10000'>
         <text id='textHelper' x='5000' y='5000' font-size='20' font-family='Grafolita Script' fill='#00ff00'>holala</text>
     </svg>
     
@@ -208,6 +226,7 @@
 
     <script src="js/themeManager.js"></script>
     <script src="js/controllers/compsSelection/CompsSelectionSettingsController.js"></script>
+    <script src="js/controllers/compsSelection/ExtraCompsSelectionSettingsController.js"></script>
     <script src="js/utils/messageParser.js"></script>
     <script src="js/controllers/CompSelectionController.js"></script>
     <script src="js/controllers/CompRenderController.js"></script>
@@ -280,7 +299,11 @@
             </div>
         </div>
     </script>
-
+    <script id="extraCompsSelectionTemplate" type="text/html">
+        <tr class="extraCompElement">
+            <td class="name"></td>
+        </tr>
+    </script>
         
 </body>
 </html>
diff --git a/extension/js/controllers/CompSelectionController.js b/extension/js/controllers/CompSelectionController.js
index 10ba4bc..105d901 100644
--- a/extension/js/controllers/CompSelectionController.js
+++ b/extension/js/controllers/CompSelectionController.js
@@ -77,7 +77,7 @@
         }
         
         function showElemSetings() {
-            settingsManager.show(comp.settings, saveSettings);
+            settingsManager.show(comp.settings, saveSettings, compositions);
         }
         
         function overElemSetings() {
diff --git a/extension/js/controllers/compsSelection/CompsSelectionSettingsController.js b/extension/js/controllers/compsSelection/CompsSelectionSettingsController.js
index e1c622c..9305c83 100644
--- a/extension/js/controllers/compsSelection/CompsSelectionSettingsController.js
+++ b/extension/js/controllers/compsSelection/CompsSelectionSettingsController.js
@@ -1,10 +1,10 @@
 var SelectionSettings = function (view) {
         
     var ob = {}, settingsView, compData, tempData = {}, callback;
-    var segments, segmentsCheckbox, segmentsTextBox;
+    var segments, segmentsCheckbox, segmentsTextBox, compositions;
     var standalone, standaloneCheckbox;
     var demo, demoCheckbox;
-    var glyphs,hiddens,guideds, glyphsCheckbox,guidedsCheckbox,hiddensCheckbox;
+    var glyphs,hiddens,guideds,extraComps, glyphsCheckbox,guidedsCheckbox,hiddensCheckbox, extraCompsCheckbox;
 
     function updateSegmentsData() {
         if (tempData.segmented) {
@@ -50,6 +50,16 @@
             hiddensCheckbox.removeClass('selected');
         }
     }
+    function updateExtraCompsData() {
+        if (tempData.extraComps && tempData.extraComps.active) {
+            extraCompsCheckbox.addClass('selected');
+            ExtraCompsSelectionSettingsController.show();
+            ExtraCompsSelectionSettingsController.updateList(compositions,tempData.extraComps.list);
+        } else {
+            extraCompsCheckbox.removeClass('selected');
+            ExtraCompsSelectionSettingsController.hide();
+        }
+    }
 
     function updateGuidedsData() {
         if (tempData.guideds) {
@@ -89,6 +99,12 @@
         mainController.saveData();
     }
 
+    function handleExtraCompsCheckboxClick() {
+        tempData.extraComps.active = !tempData.extraComps.active;
+        updateExtraCompsData();
+        mainController.saveData();
+    }
+
     function handleGuidedsCheckboxClick() {
         tempData.guideds = !tempData.guideds;
         updateGuidedsData();
@@ -123,13 +139,17 @@
         glyphs.find('.checkboxCombo').on('click', handleGlyphsCheckboxClick);
         hiddens = settingsView.find('.hiddens');
         hiddens.find('.checkboxCombo').on('click', handleHiddensCheckboxClick);
+        extraComps = settingsView.find('.extraComps');
+        extraComps.find('.checkboxCombo').on('click', handleExtraCompsCheckboxClick);
         guideds = settingsView.find('.guideds');
         guideds.find('.checkboxCombo').on('click', handleGuidedsCheckboxClick);
         glyphsCheckbox = glyphs.find('.checkbox');
         hiddensCheckbox = hiddens.find('.checkbox');
+        extraCompsCheckbox = extraComps.find('.checkbox');
         guidedsCheckbox = guideds.find('.checkbox');
         settingsView.find('.buttons .cancel').on('click', cancelSettings);
         settingsView.find('.buttons .return').on('click', saveSettings);
+        ExtraCompsSelectionSettingsController.init(settingsView);
         updateAllData();
     }
     
@@ -139,14 +159,16 @@
         updateDemoData();
         updateGlyphsData();
         updateHiddensData();
+        updateExtraCompsData();
         updateGuidedsData();
     }
 
-    function show(data, cb) {
+    function show(data, cb, comps) {
         settingsView.show();
         compData = data;
         tempData = JSON.parse(JSON.stringify(compData));
         callback = cb;
+        compositions = comps;
         updateAllData();
     }
 
diff --git a/extension/js/controllers/compsSelection/ExtraCompsSelectionSettingsController.js b/extension/js/controllers/compsSelection/ExtraCompsSelectionSettingsController.js
new file mode 100644
index 0000000..bde8140
--- /dev/null
+++ b/extension/js/controllers/compsSelection/ExtraCompsSelectionSettingsController.js
@@ -0,0 +1,151 @@
+var ExtraCompsSelectionSettingsController = (function(){
+    var ob = {};
+    ob.init = init;
+    ob.show = show;
+    ob.hide = hide;
+    ob.updateList = updateList;
+
+    var compositionsContainer;
+    var template;
+    var compsList = [], selectedList;
+
+    function handleElementClick(ev){
+        var closest = $(ev.target).closest('tr');
+        var id = closest.attr('data-comp-id');
+        toggleCompSelection(id);
+    }
+
+    function toggleCompSelection(id){
+        console.log('toggleCompSelection:',id);
+        var i = 0, len = compsList.length;
+        while(i<len){
+            if(compsList[i].id == id){
+                compsList[i].selected = !compsList[i].selected;
+                if(compsList[i].selected){
+                    compsList[i].elem.addClass('selected');
+                    selectedList.push(id);
+                } else {
+                    compsList[i].elem.removeClass('selected');
+                    selectedList.splice(selectedList.indexOf(id),1);
+                }
+                break;
+            }
+            i += 1;
+
+        }
+        console.log(selectedList);
+    }
+
+    function markCompsAsSelected(){
+
+        var i, len = selectedList.length, j, jLen = compsList.length, id;
+        for(i=0;i<len;i+=1){
+            j = 0;
+            id = selectedList[i];
+            while(j<jLen){
+                if(compsList[j].id == id){
+                    compsList[j].selected = true;
+                    compsList[j].elem.addClass('selected');
+                    break;
+                }
+                j += 1;
+            }
+            if(j === jLen){
+                selectedList.splice(i,1);
+                i -= 1;
+                len -= 1;
+            }
+        }
+
+
+
+        var j = 0, len = compsList.length;
+
+    }
+
+    function init(element){
+        compositionsContainer = element.find('.extraCompositions').find('tbody');
+        compositionsContainer.hide();
+        compositionsContainer.on('click', handleElementClick);
+    }
+
+    function show(){
+        compositionsContainer.show();
+    }
+
+    function hide(){
+        compositionsContainer.hide();
+    }
+
+    function markCompsAsErasable(){
+        var i, len = compsList.length;
+        for(i=0;i<len;i+=1){
+            compsList[i].erasable = true;
+        }
+    }
+
+    function removeMarkedComps(){
+        var i, len = compsList.length;
+        for(i=0;i<len;i+=1){
+            if(compsList[i].erasable){
+                compositionsContainer.remove(compsList[i].elem);
+                compsList.splice(i,1);
+                i -= 1;
+                len -= 1;
+            }
+            compsList[i].erasable = true;
+        }
+    }
+
+    function findCompElementData(elementData){
+        var i = 0, len = compsList.length, compData;
+        while(i<len){
+            if(compsList[i].id == elementData.id){
+                compData = compsList[i];
+                compData.erasable = false;
+                break;
+            }
+            i += 1;
+        }
+        var compElement;
+        if(!compData){
+            compElement = $(Mustache.render(template));
+            compData = {
+                erasable: false,
+                id: elementData.id,
+                elem: compElement,
+                selected: false
+            };
+            compElement.attr('data-comp-id',compData.id);
+            compsList.push(compData);
+        }
+        compData.selected = false;
+        compElement = compData.elem;
+        compElement.removeClass('selected');
+        compElement.find('.name').text(elementData.name);
+        return compData;
+    }
+
+    function updateList(compositions, selected){
+        selectedList = selected;
+        if(!template){
+            template = document.getElementById('extraCompsSelectionTemplate').innerHTML;
+        }
+        markCompsAsErasable();
+        var i, len = compositions.length, compData;
+        for(i=0;i<len;i+=1){
+            compData = findCompElementData(compositions[i]);
+            compositionsContainer.append(compData.elem);
+        }
+        markCompsAsSelected();
+        removeMarkedComps();
+        //
+        //template = document.getElementById('fontTemplate').innerHTML;
+        //output = Mustache.render(template, {fontData: fonts[i], storedData: storedData});
+        //fontElem = $(output);
+
+    }
+
+
+    return ob;
+}());
\ No newline at end of file
diff --git a/extension/jsx/compsManager.jsx b/extension/jsx/compsManager.jsx
index 198c584..7bce26b 100644
--- a/extension/jsx/compsManager.jsx
+++ b/extension/jsx/compsManager.jsx
@@ -29,10 +29,20 @@
                     demo: false,
                     glyphs: true,
                     hiddens: false,
+                    extraComps: {
+                        active: false,
+                        list:[]
+                    },
                     guideds: false
                 }
             };
         }
+        if(!compData.settings.extraComps){
+            compData.settings.extraComps = {
+                active: false,
+                list:[]
+            }
+        }
         
         compData.name = comp.name;
         
diff --git a/extension/jsx/elements/layerElement.jsx b/extension/jsx/elements/layerElement.jsx
index 1de09aa..94c63e1 100644
--- a/extension/jsx/elements/layerElement.jsx
+++ b/extension/jsx/elements/layerElement.jsx
@@ -76,9 +76,9 @@
                 curLayer = layerOb;
                 instanceOfArray = [AVLayer, CameraLayer, LightLayer, ShapeLayer, TextLayer];
                 instanceOfArrayLength = instanceOfArray.length;
-                if (curLayer.guideLayer) {
+                /*if (curLayer.guideLayer) {
                     return ob.layerTypes.guide;
-                } else if (curLayer.adjustmentLayer) {
+                } else */if (curLayer.adjustmentLayer) {
                     return ob.layerTypes.adjustment;
                 } else if (curLayer.nullLayer) {
                     return ob.layerTypes.nullLayer;
@@ -113,10 +113,16 @@
             layerData.isValid = false;
             layerData.render = false;
         }
-        if (layerType === ob.layerTypes.guide) {
+        /*if (layerType === ob.layerTypes.guide) {
+            layerData.isGuide = true;
+            layerData.render = false;
+        }*/
+
+        if(layerInfo.guideLayer){
             layerData.isGuide = true;
             layerData.render = false;
         }
+
         if (layerInfo.enabled === false) {
             layerData.enabled = false;
             layerData.render = false;
diff --git a/extension/jsx/projectManager.jsx b/extension/jsx/projectManager.jsx
index 5ce4647..3e98efa 100644
--- a/extension/jsx/projectManager.jsx
+++ b/extension/jsx/projectManager.jsx
@@ -71,10 +71,22 @@
         }
         return arr;
     }
+
+    function getCompositionById(id){
+        var i, numItems = project.numItems;
+        for (i = 0; i < numItems; i += 1) {
+            if (getItemType(project.item(i + 1)) === 'Comp') {
+                if(project.item(i + 1).id == id){
+                    return project.item(i + 1);
+                }
+            }
+        }
+    }
     
     var ob = {
         checkProject: checkProject,
         getCompositions: getCompositions,
+        getCompositionById: getCompositionById,
         searchCommands: searchCommands,
         getCommandID: getCommandID
     };
diff --git a/extension/jsx/renderManager.jsx b/extension/jsx/renderManager.jsx
index eab2b34..0225812 100644
--- a/extension/jsx/renderManager.jsx
+++ b/extension/jsx/renderManager.jsx
@@ -1,10 +1,11 @@
 /*jslint vars: true , plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */
-/*global bm_layerElement, bm_eventDispatcher, bm_sourceHelper, bm_generalUtils, bm_compsManager, bm_downloadManager, bm_textShapeHelper, bm_markerHelper, app, File, bm_dataManager*/
+/*global bm_layerElement,bm_projectManager, bm_eventDispatcher, bm_sourceHelper, bm_generalUtils, bm_compsManager, bm_downloadManager, bm_textShapeHelper, bm_markerHelper, app, File, bm_dataManager*/
 
 var bm_renderManager = (function () {
     'use strict';
     
     var ob = {}, pendingLayers = [], pendingComps = [], destinationPath, fsDestinationPath, currentCompID, totalLayers, currentLayer, currentCompSettings, hasExpressionsFlag;
+    var currentExportedComps = [];
     
     function restoreParents(layers) {
         
@@ -36,7 +37,7 @@
         }
     }
     
-    function createLayers(comp, layers, framerate) {
+    function createLayers(comp, layers, framerate, deepTraversing) {
         var i, len = comp.layers.length, layerInfo, layerData, prevLayerData;
         for (i = 0; i < len; i += 1) {
             layerInfo = comp.layers[i + 1];
@@ -82,13 +83,17 @@
                 bm_textShapeHelper.addComps();
             }
             if (layerData.ty === bm_layerElement.layerTypes.precomp && layerData.render !== false && layerData.compId) {
-                layerData.layers = [];
-                createLayers(layerInfo.source, layerData.layers, framerate);
+                currentExportedComps.push(layerData.compId);
+                if(deepTraversing){
+                    layerData.layers = [];
+                    createLayers(layerInfo.source, layerData.layers, framerate, deepTraversing);
+                }
             }
         }
     }
     
     function render(comp, destination, fsDestination, compSettings) {
+        currentExportedComps = [];
         bm_ProjectHelper.init();
         hasExpressionsFlag = false;
         currentCompID = comp.id;
@@ -113,13 +118,42 @@
             w : comp.width,
             h : comp.height
         };
+        currentExportedComps.push(currentCompID);
         ob.renderData.exportData = exportData;
         ob.renderData.firstFrame = exportData.ip * comp.frameRate;
-        createLayers(comp, exportData.layers, exportData.fr);
+        createLayers(comp, exportData.layers, exportData.fr, true);
+        exportExtraComps(exportData);
         totalLayers = pendingLayers.length;
         currentLayer = 0;
         app.scheduleTask('bm_renderManager.renderNextLayer();', 20, false);
     }
+
+    function exportExtraComps(exportData){
+        var list = currentCompSettings.extraComps.list;
+        var i, len = list.length, compData;
+        bm_eventDispatcher.log(currentExportedComps);
+        var j, jLen = currentExportedComps.length;
+        for(i=0;i<len;i+=1){
+            j = 0;
+            while(j<jLen){
+                if(currentExportedComps[j] === list[i]){
+                    break;
+                }
+                j += 1;
+            }
+            if(j===jLen){
+                var comp = bm_projectManager.getCompositionById(list[i]);
+                compData = {
+                    layers: [],
+                    id: comp.id,
+                    nm: comp.name,
+                    xt: 1
+                };
+                createLayers(comp, compData.layers, exportData.fr, false);
+                exportData.comps.push(compData);
+            }
+        }
+    }
     
     function reset() {
         pendingLayers.length = 0;
@@ -182,6 +216,7 @@
             bm_eventDispatcher.sendEvent('bm:render:update', {type: 'update', message: 'Rendering layer: ' + nextLayerData.layer.name, compId: currentCompID, progress: currentLayer / totalLayers});
             bm_layerElement.renderLayer(nextLayerData);
         } else {
+            bm_eventDispatcher.log(currentCompSettings.extraComps.list.length);
             removeExtraData();
             bm_sourceHelper.exportImages(destinationPath, ob.renderData.exportData.assets, currentCompID);
         }
diff --git a/extension/jsx/utils/expressionHelper.jsx b/extension/jsx/utils/expressionHelper.jsx
index 1ab8a25..365ff42 100644
--- a/extension/jsx/utils/expressionHelper.jsx
+++ b/extension/jsx/utils/expressionHelper.jsx
@@ -213,11 +213,12 @@
                 return element;
             case "BinaryExpression":
                 return convertBinaryExpression(element);
+            case "UnaryExpression":
+                return convertUnaryExpression(element);
             case "MemberExpression":
                 handleMemberExpression(element);
                 return element;
             case "UpdateExpression":
-            case "UnaryExpression":
                 return element;
             default:
                 //bm_eventDispatcher.log('es: ', element);
@@ -271,9 +272,28 @@
         return callStatementOb;
     }
 
+    function convertUnaryExpression(expression){
+        if(expression.operator === '-' && expression.argument.type !== 'Literal'){
+            var callStatementOb = {
+                'arguments': [
+                    getBinaryElement(expression.argument)
+                ],
+                type: "CallExpression",
+                callee: {
+                    name: '$bm_neg',
+                    type: 'Identifier'
+                }
+            };
+            return callStatementOb;
+        }
+        return expression;
+    }
+
     function handleMemberExpression(expression) {
         if (expression.property.type === 'BinaryExpression') {
             expression.property = convertBinaryExpression(expression.property);
+        } else if (expression.property.type === 'UnaryExpression') {
+            expression.property = convertUnaryExpression(expression.property);
         } else if (expression.property.type === 'CallExpression') {
             handleCallExpression(expression.property);
         }
@@ -285,6 +305,8 @@
         for (i = 0; i < len; i += 1) {
             if (args[i].type === 'BinaryExpression') {
                 args[i] = convertBinaryExpression(args[i]);
+            } else if (args[i].type === 'UnaryExpression') {
+                args[i] = convertUnaryExpression(args[i]);
             }
         }
     }
@@ -364,6 +386,8 @@
             if (declarations[i].init) {
                 if (declarations[i].init.type === 'BinaryExpression') {
                     declarations[i].init = convertBinaryExpression(declarations[i].init);
+                } else if (declarations[i].init.type === 'UnaryExpression') {
+                    declarations[i].init = convertUnaryExpression(declarations[i].init);
                 } else if (declarations[i].init.type === 'CallExpression') {
                     handleCallExpression(declarations[i].init);
                 }
@@ -375,6 +399,8 @@
         if(assignmentExpression.right){
             if(assignmentExpression.right.type === 'BinaryExpression') {
                 assignmentExpression.right = convertBinaryExpression(assignmentExpression.right);
+            } else if (assignmentExpression.right.type === 'UnaryExpression') {
+                assignmentExpression.right = convertUnaryExpression(assignmentExpression.right);
             } else if (assignmentExpression.right.type === 'CallExpression') {
                 handleCallExpression(assignmentExpression.right);
             }
@@ -386,6 +412,8 @@
             handleCallExpression(expressionStatement.expression);
         } else if (expressionStatement.expression.type === 'BinaryExpression') {
             expressionStatement.expression = convertBinaryExpression(expressionStatement.expression);
+        } else if (expressionStatement.expression.type === 'UnaryExpression') {
+            expressionStatement.expression = convertUnaryExpression(expressionStatement.expression);
         } else if (expressionStatement.expression.type === 'AssignmentExpression') {
             handleAssignmentExpression(expressionStatement.expression);
         }
@@ -453,6 +481,10 @@
             assignmentObject = createAssignmentObject();
             assignmentObject.expression.right = expressionStatement.expression;
             return assignmentObject;
+        } else if(expressionStatement.expression.type === 'AssignmentExpression'){
+            assignmentObject = createAssignmentObject();
+            assignmentObject.expression.right = expressionStatement.expression;
+            return assignmentObject;
         }
         return expressionStatement;
     }
@@ -516,7 +548,6 @@
 
     function checkExpression(prop, returnOb) {
         if (prop.expressionEnabled && !prop.expressionError) {
-            //([.'"])name([\s'"]) replace .name
             pendingBodies.length = 0;
             doneBodies.length = 0;
             expressionStr = prop.expression;
@@ -538,7 +569,7 @@
     }
     
     function renameNameProperty(str){
-        var regName = /([.'"])name([\s'";.])/g;
+        var regName = /([.'"])name([\s'";.\)\]])/g;
         return str.replace(regName,'$1_name$2');
     }
     
diff --git a/extension/jsx/utils/textHelper.jsx b/extension/jsx/utils/textHelper.jsx
index 23e9054..858cee9 100644
--- a/extension/jsx/utils/textHelper.jsx
+++ b/extension/jsx/utils/textHelper.jsx
@@ -34,11 +34,18 @@
         ob.s = textDocument.fontSize;
         ob.f = textDocument.font;
         bm_sourceHelper.addFont(textDocument.font, textDocument.fontFamily, textDocument.fontStyle);
-        ob.t = textDocument.text;
+        ob.t = textDocument.allCaps ? textDocument.text.toUpperCase() : textDocument.text; // text to caps if needed
         len = ob.t.length;
         bm_textShapeHelper.addTextLayer(layerInfo);
         ob.j = getJustification(textDocument.justification);
         ob.tr = textDocument.tracking;
+        bm_eventDispatcher.log(textDocument.baselineLocs);
+        bm_eventDispatcher.log(textDocument.baselineLocs.length);
+        if(textDocument.baselineLocs && textDocument.baselineLocs.length > 5){
+            ob.lh = textDocument.baselineLocs[5] - textDocument.baselineLocs[1];
+        } else {
+            ob.lh = ob.s*1.2;
+        }
         if (textDocument.applyFill) {
             len = textDocument.fillColor.length;
             ob.fc = [];
diff --git a/extension/jsx/utils/textShapeHelper.jsx b/extension/jsx/utils/textShapeHelper.jsx
index fa71594..c8cc45a 100644
--- a/extension/jsx/utils/textShapeHelper.jsx
+++ b/extension/jsx/utils/textShapeHelper.jsx
@@ -171,7 +171,7 @@
             var fontFamily = textDocument.fontFamily;
             var fontStyle = textDocument.fontStyle;
             var fontSize = textDocument.fontSize;
-            var text = textDocument.text;
+            var text = textDocument.allCaps ? textDocument.text.toUpperCase() : textDocument.text;
             var j, jLen = text.length;
             
             if (currentFont !== font) {
diff --git a/player/index.html b/player/index.html
index 50c6b5f..5e1d421 100644
--- a/player/index.html
+++ b/player/index.html
@@ -9,11 +9,11 @@
             overflow-x: hidden;
             overflow-y: auto;
         }
-        #bodymovin,#bodymovin2{
-            background-color:#333;
-            width:1500px;
-            height:700px;
 
+        #bodymovin{
+            background-color:#333;
+            width:1000px;
+            height:700px;
             /*width:800px;
             height:500px;*/
             display:block;
@@ -60,6 +60,8 @@
     <script src="js/utils/shapes/ShapeModifiers.js"></script>
     <script src="js/utils/shapes/TrimModifier.js"></script>
     <script src="js/utils/shapes/RoundCornersModifier.js"></script>
+    <script src="js/utils/imagePreloader.js"></script>
+    <script src="js/renderers/BaseRenderer.js"></script>
     <script src="js/renderers/SVGRenderer.js"></script>
     <script src="js/renderers/CanvasRenderer.js"></script>
     <script src="js/renderers/HybridRenderer.js"></script>
@@ -68,7 +70,6 @@
     <script src="js/elements/svgElements/SVGBaseElement.js"></script>
     <script src="js/elements/TextElement.js"></script>
     <script src="js/elements/svgElements/SVGTextElement.js"></script>
-    <script src="js/elements/PlaceHolderElement.js"></script>
     <script src="js/elements/CompElement.js"></script>
     <script src="js/elements/ImageElement.js"></script>
     <script src="js/elements/ShapeElement.js"></script>
@@ -96,6 +97,7 @@
     <script src="js/utils/expressions/ShapeInterface.js"></script>
     <script src="js/utils/expressions/LayerInterface.js"></script>
     <script src="js/utils/expressions/CompInterface.js"></script>
+    <script src="js/utils/expressions/ProjectInterface.js"></script>
     <script src="js/effects/SliderEffect.js"></script>
     <script src="js/effects.js"></script>
     <!-- end Expressions -->
@@ -112,7 +114,7 @@
     var anim;
     var animData = {
         container: document.getElementById('bodymovin'),
-        renderer: 'html',
+        renderer: 'canvas',
         loop: false,
         autoplay: true,
         autoloadSegments: true,
diff --git a/player/js/animation/AnimationItem.js b/player/js/animation/AnimationItem.js
index 7e776cd..3ddb752 100644
--- a/player/js/animation/AnimationItem.js
+++ b/player/js/animation/AnimationItem.js
@@ -28,6 +28,7 @@
     this.subframeEnabled = subframeEnabled;
     this.segments = [];
     this.pendingSegment = false;
+    this.projectInterface = ProjectInterface();
 };
 
 AnimationItem.prototype.setParams = function(params) {
@@ -52,6 +53,7 @@
             this.renderer = new HybridRenderer(this, params.rendererSettings);
             break;
     }
+    this.renderer.setProjectInterface(this.projectInterface);
     this.animType = animType;
 
     if(params.loop === '' || params.loop === null){
@@ -168,7 +170,6 @@
     //this.animationData.tf = 50;
     dataManager.completeData(this.animationData,this.renderer.globalData.fontManager);
     this.renderer.includeLayers(data.layers);
-    this.renderer.buildStage(this.container, this.layers);
     if(expressionsPlugin){
         expressionsPlugin.initExpressions(this);
     }
@@ -226,6 +227,7 @@
         animData.assets = animData.assets.concat(animData.comps);
         animData.comps = null;
     }
+    this.renderer.searchExtraCompositions(animData.assets);
 
     this.layers = this.animationData.layers;
     this.assets = this.animationData.assets;
@@ -233,6 +235,10 @@
     this.firstFrame = Math.round(this.animationData.ip);
     this.frameMult = this.animationData.fr / 1000;
     this.trigger('config_ready');
+    this.imagePreloader = new ImagePreloader();
+    this.imagePreloader.setAssetsPath(this.assetsPath);
+    this.imagePreloader.setPath(this.path);
+    this.imagePreloader.loadAssets(animData.assets);
     this.loadSegments();
     this.updaFrameModifier();
     if(this.renderer.globalData.fontManager){
@@ -247,7 +253,7 @@
     function checkFontsLoaded(){
         if(this.renderer.globalData.fontManager.loaded){
             dataManager.completeData(this.animationData,this.renderer.globalData.fontManager);
-            this.renderer.buildItems(this.animationData.layers);
+            //this.renderer.buildItems(this.animationData.layers);
             this.checkLoaded();
         }else{
             setTimeout(checkFontsLoaded.bind(this),20);
@@ -270,10 +276,10 @@
 
 AnimationItem.prototype.checkLoaded = function () {
     if (this.pendingElements === 0) {
-        this.renderer.buildStage(this.container, this.layers);
         if(expressionsPlugin){
             expressionsPlugin.initExpressions(this);
         }
+        this.renderer.initItems();
         this.trigger('DOMLoaded');
         this.isLoaded = true;
         this.gotoFrame();
diff --git a/player/js/elements/BaseElement.js b/player/js/elements/BaseElement.js
index aad5777..1b5cc4e 100644
--- a/player/js/elements/BaseElement.js
+++ b/player/js/elements/BaseElement.js
@@ -14,6 +14,12 @@
     return false;
 }
 
+BaseElement.prototype.checkParenting = function(){
+    if(this.data.parent !== undefined){
+        this.comp.buildElementParenting(this, this.data.parent);
+    }
+}
+
 BaseElement.prototype.prepareFrame = function(num){
     if(this.data.ip - this.data.st <= num && this.data.op - this.data.st > num)
     {
@@ -57,6 +63,20 @@
     this.currentFrameNum = num*this.data.sr;
     return this.isVisible;
 };
+
+BaseElement.prototype.initExpressions = function(){
+    this.layerInterface = LayerExpressionInterface(this);
+    //layers[i].layerInterface = LayerExpressionInterface(layers[i]);
+    if(this.data.hasMask){
+        this.layerInterface.registerMaskInterface(this.maskManager);
+    }
+    if(this.data.ty === 0 || this.data.xt){
+        this.compInterface = CompExpressionInterface(this);
+    } else if(this.data.ty === 4){
+        this.layerInterface.shapeInterface = ShapeExpressionInterface.createShapeInterface(this.shapesData,this.viewData,this.layerInterface);
+    }
+}
+
 BaseElement.prototype.setBlendMode = function(){
     var blendModeValue = '';
     switch(this.data.bm){
@@ -124,20 +144,22 @@
     this.isVisible = false;
     this.currentFrameNum = -99999;
     this.lastNum = -99999;
-    this.finalTransform = {
-        mProp: PropertyFactory.getProp(this,this.data.ks,2,null,this.dynamicProperties),
-        matMdf: false,
-        opMdf: false,
-        mat: new Matrix(),
-        opacity: 1
-    };
-    this.finalTransform.op = this.finalTransform.mProp.o;
-    this.transform = this.finalTransform.mProp;
-    if(this.data.ty !== 11){
-        this.createElements();
-    }
-    if(this.data.hasMask){
-        this.addMasks(this.data);
+    if(this.data.ks){
+        this.finalTransform = {
+            mProp: PropertyFactory.getProp(this,this.data.ks,2,null,this.dynamicProperties),
+            matMdf: false,
+            opMdf: false,
+            mat: new Matrix(),
+            opacity: 1
+        };
+        this.finalTransform.op = this.finalTransform.mProp.o;
+        this.transform = this.finalTransform.mProp;
+        if(this.data.ty !== 11){
+            this.createElements();
+        }
+        if(this.data.hasMask){
+            this.addMasks(this.data);
+        }
     }
 };
 BaseElement.prototype.getType = function(){
diff --git a/player/js/elements/CompElement.js b/player/js/elements/CompElement.js
index 6b3ef2e..ebda070 100644
--- a/player/js/elements/CompElement.js
+++ b/player/js/elements/CompElement.js
@@ -1,22 +1,28 @@
 function ICompElement(data,parentContainer,globalData,comp, placeholder){
     this._parent.constructor.call(this,data,parentContainer,globalData,comp, placeholder);
     this.layers = data.layers;
-    this.isSvg = true;
+    this.supports3d = true;
+    this.completeLayers = false;
+    this.elements = Array.apply(null,{length:this.layers.length});
     if(this.data.tm){
         this.tm = PropertyFactory.getProp(this,this.data.tm,0,globalData.frameRate,this.dynamicProperties);
     }
+    if(this.data.xt){
+        this.layerElement = document.createElementNS(svgNS,'g');
+        this.buildAllItems();
+    } else if(!globalData.progressiveLoad){
+        this.buildAllItems();
+    }
 }
 createElement(SVGBaseElement, ICompElement);
 
-ICompElement.prototype.getComposingElement = function(){
-    return this.layerElement;
-};
-
 ICompElement.prototype.hide = function(){
     if(!this.hidden){
         var i,len = this.elements.length;
         for( i = 0; i < len; i+=1 ){
-            this.elements[i].hide();
+            if(this.elements[i]){
+                this.elements[i].hide();
+            }
         }
         this.hidden = true;
     }
@@ -24,7 +30,7 @@
 
 ICompElement.prototype.prepareFrame = function(num){
     this._parent.prepareFrame.call(this,num);
-    if(this.isVisible===false){
+    if(this.isVisible===false && !this.data.xt){
         return;
     }
     var timeRemapped = num;
@@ -36,8 +42,16 @@
     }
     this.renderedFrame = timeRemapped/this.data.sr;
     var i,len = this.elements.length;
+    if(!this.completeLayers){
+        this.checkLayers(this.renderedFrame);
+    }
     for( i = 0; i < len; i+=1 ){
-        this.elements[i].prepareFrame(timeRemapped/this.data.sr - this.layers[i].st);
+        /*if(!this.elements[i]){
+            this.checkLayer(i, this.renderedFrame - this.layers[i].st, this.layerElement);
+        }*/
+        if(this.completeLayers || this.elements[i]){
+            this.elements[i].prepareFrame(timeRemapped/this.data.sr - this.layers[i].st);
+        }
     }
 };
 
@@ -51,7 +65,9 @@
 
     this.hidden = false;
     for( i = 0; i < len; i+=1 ){
-        this.elements[i].renderFrame();
+        if(this.completeLayers || this.elements[i]){
+            this.elements[i].renderFrame();
+        }
     }
     if(this.firstFrame){
         this.firstFrame = false;
@@ -70,6 +86,21 @@
     this._parent.destroy.call();
     var i,len = this.layers.length;
     for( i = 0; i < len; i+=1 ){
-        this.elements[i].destroy();
+        if(this.elements[i]){
+            this.elements[i].destroy();
+        }
     }
-};
\ No newline at end of file
+};
+
+ICompElement.prototype.checkLayers = SVGRenderer.prototype.checkLayers;
+ICompElement.prototype.buildItem = SVGRenderer.prototype.buildItem;
+ICompElement.prototype.buildAllItems = SVGRenderer.prototype.buildAllItems;
+ICompElement.prototype.buildElementParenting = SVGRenderer.prototype.buildElementParenting;
+ICompElement.prototype.createItem = SVGRenderer.prototype.createItem;
+ICompElement.prototype.createImage = SVGRenderer.prototype.createImage;
+ICompElement.prototype.createComp = SVGRenderer.prototype.createComp;
+ICompElement.prototype.createSolid = SVGRenderer.prototype.createSolid;
+ICompElement.prototype.createShape = SVGRenderer.prototype.createShape;
+ICompElement.prototype.createText = SVGRenderer.prototype.createText;
+ICompElement.prototype.createBase = SVGRenderer.prototype.createBase;
+ICompElement.prototype.appendElementInPos = SVGRenderer.prototype.appendElementInPos;
\ No newline at end of file
diff --git a/player/js/elements/ImageElement.js b/player/js/elements/ImageElement.js
index 4d88d71..d589fc4 100644
--- a/player/js/elements/ImageElement.js
+++ b/player/js/elements/ImageElement.js
@@ -6,30 +6,17 @@
 
 IImageElement.prototype.createElements = function(){
 
-    var self = this;
-
-    var imageLoaded = function(){
-        self.innerElem.setAttributeNS('http://www.w3.org/1999/xlink','href',assetPath);
-        self.maskedElement = self.innerElem;
-    };
-
-    var img = new Image();
-    img.addEventListener('load', imageLoaded, false);
-    img.addEventListener('error', imageLoaded, false);
-
     var assetPath = this.globalData.getAssetsPath(this.assetData);
-    img.src = assetPath;
 
     this._parent.createElements.call(this);
 
     this.innerElem = document.createElementNS(svgNS,'image');
     this.innerElem.setAttribute('width',this.assetData.w+"px");
     this.innerElem.setAttribute('height',this.assetData.h+"px");
-    if(this.layerElement === this.parentContainer){
-        this.appendNodeToParent(this.innerElem);
-    }else{
-        this.layerElement.appendChild(this.innerElem);
-    }
+    this.innerElem.setAttribute('preserveAspectRatio','xMidYMid slice');
+    this.innerElem.setAttributeNS('http://www.w3.org/1999/xlink','href',assetPath);
+    this.maskedElement = this.innerElem;
+    this.layerElement.appendChild(this.innerElem);
     if(this.data.ln){
         this.innerElem.setAttribute('id',this.data.ln);
     }
@@ -41,7 +28,7 @@
 
 IImageElement.prototype.hide = function(){
     if(!this.hidden){
-        this.innerElem.setAttribute('visibility','hidden');
+        this.innerElem.style.display = 'none';
         this.hidden = true;
     }
 };
@@ -54,7 +41,7 @@
     }
     if(this.hidden){
         this.hidden = false;
-        this.innerElem.setAttribute('visibility', 'visible');
+        this.innerElem.style.display = 'block';
     }
     if(this.firstFrame){
         this.firstFrame = false;
diff --git a/player/js/elements/SolidElement.js b/player/js/elements/SolidElement.js
index 17c3fa8..08ba4bf 100644
--- a/player/js/elements/SolidElement.js
+++ b/player/js/elements/SolidElement.js
@@ -13,11 +13,7 @@
     rect.setAttribute('width',this.data.sw);
     rect.setAttribute('height',this.data.sh);
     rect.setAttribute('fill',this.data.sc);
-    if(this.layerElement === this.parentContainer){
-        this.appendNodeToParent(rect);
-    }else{
-        this.layerElement.appendChild(rect);
-    }
+    this.layerElement.appendChild(rect);
     this.innerElem = rect;
     if(this.data.ln){
         this.innerElem.setAttribute('id',this.data.ln);
diff --git a/player/js/elements/TextElement.js b/player/js/elements/TextElement.js
index e5feab6..647b1f3 100644
--- a/player/js/elements/TextElement.js
+++ b/player/js/elements/TextElement.js
@@ -4,7 +4,7 @@
     this._parent.init.call(this);
     this.lettersChangedFlag = false;
     var data = this.data;
-    this.renderedLetters = Array.apply(null,{length:data.t.d.l.length});
+    this.renderedLetters = Array.apply(null,{length:data.t.d.l ? data.t.d.l.length : 0});
     this.viewData = {
         m:{
             a: PropertyFactory.getProp(this,data.t.m.a,1,0,this.dynamicProperties)
diff --git a/player/js/elements/canvasElements/CVBaseElement.js b/player/js/elements/canvasElements/CVBaseElement.js
index 7b565ae..42866ee 100644
--- a/player/js/elements/canvasElements/CVBaseElement.js
+++ b/player/js/elements/canvasElements/CVBaseElement.js
@@ -9,7 +9,7 @@
 createElement(BaseElement, CVBaseElement);
 
 CVBaseElement.prototype.createElements = function(){
-
+    this.checkParenting();
 };
 
 CVBaseElement.prototype.checkBlendMode = function(globalData){
diff --git a/player/js/elements/canvasElements/CVCompElement.js b/player/js/elements/canvasElements/CVCompElement.js
index a64a524..3d8051d 100644
--- a/player/js/elements/canvasElements/CVCompElement.js
+++ b/player/js/elements/canvasElements/CVCompElement.js
@@ -19,6 +19,7 @@
         cTr : new Matrix(),
         cO : 1
     };
+    this.completeLayers = false;
     var i, len = 15;
     for(i=0;i<len;i+=1){
         this.contextData.saved[i] = Array.apply(null,{length:16});
@@ -34,9 +35,13 @@
     this.canvas = cv;
     this.globalData = compGlobalData;
     this.layers = data.layers;
+    this.elements = Array.apply(null,{length:this.layers.length});
     if(this.data.tm){
         this.tm = PropertyFactory.getProp(this,this.data.tm,0,globalData.frameRate,this.dynamicProperties);
     }
+    if(this.data.xt || !globalData.progressiveLoad){
+        this.buildAllItems();
+    }
 }
 createElement(CVBaseElement, CVCompElement);
 
@@ -61,7 +66,7 @@
     }
     var i,len = this.elements.length;
     for( i = 0; i < len; i+=1 ){
-        if(this.elements[i].data.ty === 0){
+        if(this.elements[i] && this.elements[i].data.ty === 0){
             this.elements[i].resize(transformCanvas);
         }
     }
@@ -71,7 +76,7 @@
     this.globalData.frameId = this.parentGlobalData.frameId;
     this.globalData.mdf = false;
     this._parent.prepareFrame.call(this,num);
-    if(this.isVisible===false){
+    if(this.isVisible===false && !this.data.xt){
         return;
     }
     var timeRemapped = num;
@@ -83,13 +88,20 @@
     }
     this.renderedFrame = timeRemapped/this.data.sr;
     var i,len = this.elements.length;
+
+    if(!this.completeLayers){
+        this.checkLayers(num);
+    }
+
     for( i = 0; i < len; i+=1 ){
-        this.elements[i].prepareFrame(timeRemapped/this.data.sr - this.layers[i].st);
-        if(this.elements[i].data.ty === 0 && this.elements[i].globalData.mdf){
-            this.globalData.mdf = true;
+        if(this.completeLayers || this.elements[i]){
+            this.elements[i].prepareFrame(timeRemapped/this.data.sr - this.layers[i].st);
+            if(this.elements[i].data.ty === 0 && this.elements[i].globalData.mdf){
+                this.globalData.mdf = true;
+            }
         }
     }
-    if(this.globalData.mdf){
+    if(this.globalData.mdf && !this.data.xt){
         this.canvasContext.clearRect(0, 0, this.data.w, this.data.h);
         this.ctxTransform(this.transformCanvas.props);
     }
@@ -102,7 +114,9 @@
     if(this.globalData.mdf){
         var i,len = this.layers.length;
         for( i = len - 1; i >= 0; i -= 1 ){
-            this.elements[i].renderFrame();
+            if(this.completeLayers || this.elements[i]){
+                this.elements[i].renderFrame();
+            }
         }
     }
     if(this.data.hasMask){
@@ -138,4 +152,15 @@
     this.layers = null;
     this.elements = null;
     this._parent.destroy.call();
-};
\ No newline at end of file
+};
+CVCompElement.prototype.checkLayers = CanvasRenderer.prototype.checkLayers;
+CVCompElement.prototype.buildItem = CanvasRenderer.prototype.buildItem;
+CVCompElement.prototype.buildAllItems = CanvasRenderer.prototype.buildAllItems;
+CVCompElement.prototype.createItem = CanvasRenderer.prototype.createItem;
+CVCompElement.prototype.createImage = CanvasRenderer.prototype.createImage;
+CVCompElement.prototype.createComp = CanvasRenderer.prototype.createComp;
+CVCompElement.prototype.createSolid = CanvasRenderer.prototype.createSolid;
+CVCompElement.prototype.createShape = CanvasRenderer.prototype.createShape;
+CVCompElement.prototype.createText = CanvasRenderer.prototype.createText;
+CVCompElement.prototype.createBase = CanvasRenderer.prototype.createBase;
+CVCompElement.prototype.buildElementParenting = CanvasRenderer.prototype.buildElementParenting;
\ No newline at end of file
diff --git a/player/js/elements/canvasElements/CVImageElement.js b/player/js/elements/canvasElements/CVImageElement.js
index c4d4ac3..0ac13fe 100644
--- a/player/js/elements/canvasElements/CVImageElement.js
+++ b/player/js/elements/canvasElements/CVImageElement.js
@@ -8,6 +8,27 @@
 CVImageElement.prototype.createElements = function(){
     var imageLoaded = function(){
         this.globalData.elementLoaded();
+        if(this.assetData.w !== this.img.width || this.assetData.h !== this.img.height){
+            var canvas = document.createElement('canvas');
+            canvas.width = this.assetData.w;
+            canvas.height = this.assetData.h;
+            var ctx = canvas.getContext('2d');
+
+            var imgW = this.img.width;
+            var imgH = this.img.height;
+            var imgRel = imgW / imgH;
+            var canvasRel = this.assetData.w/this.assetData.h;
+            var widthCrop, heightCrop;
+            if(imgRel>canvasRel){
+                heightCrop = imgH;
+                widthCrop = heightCrop*canvasRel;
+            } else {
+                widthCrop = imgW;
+                heightCrop = widthCrop/canvasRel;
+            }
+            ctx.drawImage(this.img,(imgW-widthCrop)/2,(imgH-heightCrop)/2,widthCrop,heightCrop,0,0,this.assetData.w,this.assetData.h);
+            this.img = canvas;
+        }
     }.bind(this);
     var imageFailed = function(){
         this.failed = true;
diff --git a/player/js/elements/htmlElements/HBaseElement.js b/player/js/elements/htmlElements/HBaseElement.js
index 70a2f81..847d2cb 100644
--- a/player/js/elements/htmlElements/HBaseElement.js
+++ b/player/js/elements/htmlElements/HBaseElement.js
@@ -15,7 +15,7 @@
 };
 HBaseElement.prototype.setBlendMode = BaseElement.prototype.setBlendMode;
 
-HBaseElement.prototype.appendNodeToParent = function(node) {
+/*HBaseElement.prototype.appendNodeToParent = function(node) {
     if(this.data.hd){
         return;
     }
@@ -26,12 +26,18 @@
     }else{
         this.parentContainer.appendChild(node);
     }
+};*/
+
+
+HBaseElement.prototype.getBaseElement = function(){
+    return this.baseElement;
 };
 
 HBaseElement.prototype.createElements = function(){
     if(this.data.hasMask){
         this.layerElement = document.createElementNS(svgNS,'svg');
-        this.appendNodeToParent(this.layerElement);
+        //this.appendNodeToParent(this.layerElement);
+        this.baseElement = this.layerElement;
         this.maskedElement = this.layerElement;
     }else{
         this.layerElement = this.parentContainer;
@@ -39,7 +45,8 @@
     if(this.data.ln && (this.data.ty === 4 || this.data.ty === 0)){
         if(this.layerElement === this.parentContainer){
             this.layerElement = document.createElementNS(svgNS,'g');
-            this.appendNodeToParent(this.layerElement);
+            //this.appendNodeToParent(this.layerElement);
+            this.baseElement = this.layerElement;
         }
         this.layerElement.setAttribute('id',this.data.ln);
     }
@@ -47,6 +54,7 @@
     if(this.layerElement !== this.parentContainer){
         this.placeholder = null;
     }
+    this.checkParenting();
 };
 
 HBaseElement.prototype.renderFrame = function(parentTransform){
@@ -136,4 +144,6 @@
 
 HBaseElement.prototype.setMatte = function(){
 
-}
\ No newline at end of file
+}
+
+HBaseElement.prototype.buildElementParenting = HybridRenderer.prototype.buildElementParenting;
\ No newline at end of file
diff --git a/player/js/elements/htmlElements/HCameraElement.js b/player/js/elements/htmlElements/HCameraElement.js
index 0b77099..7df3462 100644
--- a/player/js/elements/htmlElements/HCameraElement.js
+++ b/player/js/elements/htmlElements/HCameraElement.js
@@ -30,10 +30,11 @@
 HCameraElement.prototype.setup = function() {
     var i, len = this.comp.threeDElements.length, comp;
     for(i=0;i<len;i+=1){
+        //[perspectiveElem,container]
         comp = this.comp.threeDElements[i];
-        comp[0].style.perspective = comp[0].style.webkitPerspective = this.pe.v+'px';
-        comp[1].style.transformOrigin = comp[1].style.mozTransformOrigin = comp[1].style.webkitTransformOrigin = "0px 0px 0px";
-        comp[0].style.transform = comp[0].style.webkitTransform = 'matrix3d(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1)';
+        comp.perspectiveElem.style.perspective = comp.perspectiveElem.style.webkitPerspective = this.pe.v+'px';
+        comp.container.style.transformOrigin = comp.container.style.mozTransformOrigin = comp.container.style.webkitTransformOrigin = "0px 0px 0px";
+        comp.perspectiveElem.style.transform = comp.perspectiveElem.style.webkitTransform = 'matrix3d(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1)';
     }
 };
 
@@ -87,7 +88,7 @@
         var comp;
         for(i=0;i<len;i+=1){
             comp = this.comp.threeDElements[i];
-            comp[1].style.transform = comp[1].style.webkitTransform = this.mat.toCSS();
+            comp.container.style.transform = comp.container.style.webkitTransform = this.mat.toCSS();
         }
     }
     this.firstFrame = false;
diff --git a/player/js/elements/htmlElements/HCompElement.js b/player/js/elements/htmlElements/HCompElement.js
index d2aa43c..5e127a4 100644
--- a/player/js/elements/htmlElements/HCompElement.js
+++ b/player/js/elements/htmlElements/HCompElement.js
@@ -1,47 +1,46 @@
 function HCompElement(data,parentContainer,globalData,comp, placeholder){
     this._parent.constructor.call(this,data,parentContainer,globalData,comp, placeholder);
     this.layers = data.layers;
-    this.isSvg = false;
+    this.supports3d = true;
+    this.completeLayers = false;
+    this.elements = Array.apply(null,{length:this.layers.length});
     if(this.data.tm){
         this.tm = PropertyFactory.getProp(this,this.data.tm,0,globalData.frameRate,this.dynamicProperties);
     }
     if(this.data.hasMask) {
-        this.isSvg = true;
+        this.supports3d = false;
     }
+    if(this.data.xt){
+        this.layerElement = document.createElement('div');
+    }
+    this.buildAllItems();
+
 }
 createElement(HBaseElement, HCompElement);
 
-HCompElement.prototype.getDomElement = function(){
-    return this.composingElement;
-};
-
-HCompElement.prototype.getComposingElement = function(){
-    return this.layerElement;
-};
-
 HCompElement.prototype.createElements = function(){
-    this.layerElement = document.createElement('div');
-    styleDiv(this.layerElement);
+    var divElement = document.createElement('div');
+    styleDiv(divElement);
     if(this.data.ln){
-        this.layerElement.setAttribute('id',this.data.ln);
+        divElement.setAttribute('id',this.data.ln);
     }
-    this.layerElement.style.clip = 'rect(0px, '+this.data.w+'px, '+this.data.h+'px, 0px)';
-    if(this.layerElement !== this.parentContainer){
-        this.placeholder = null;
-    }
+    divElement.style.clip = 'rect(0px, '+this.data.w+'px, '+this.data.h+'px, 0px)';
     if(this.data.hasMask){
         var compSvg = document.createElementNS(svgNS,'svg');
         compSvg.setAttribute('width',this.data.w);
         compSvg.setAttribute('height',this.data.h);
         var g = document.createElementNS(svgNS,'g');
         compSvg.appendChild(g);
-        this.layerElement.appendChild(compSvg);
+        divElement.appendChild(compSvg);
         this.maskedElement = g;
-        this.composingElement = g;
+        this.baseElement = divElement;
+        this.layerElement = g;
     }else{
-        this.composingElement = this.layerElement;
+        this.layerElement = divElement;
+        this.baseElement = this.layerElement;
     }
-    this.appendNodeToParent(this.layerElement);
+    //this.appendNodeToParent(this.layerElement);
+    this.checkParenting();
 };
 
 HCompElement.prototype.hide = ICompElement.prototype.hide;
@@ -61,9 +60,24 @@
     this.hidden = false;
 
     for( i = 0; i < len; i+=1 ){
-        this.elements[i].renderFrame();
+        if(this.completeLayers || this.elements[i]){
+            this.elements[i].renderFrame();
+        }
     }
     if(this.firstFrame){
         this.firstFrame = false;
     }
-};
\ No newline at end of file
+};
+
+HCompElement.prototype.checkLayers = BaseRenderer.prototype.checkLayers;
+HCompElement.prototype.buildItem = HybridRenderer.prototype.buildItem;
+HCompElement.prototype.buildAllItems = BaseRenderer.prototype.buildAllItems;
+HCompElement.prototype.createItem = HybridRenderer.prototype.createItem;
+HCompElement.prototype.buildElementParenting = HybridRenderer.prototype.buildElementParenting;
+HCompElement.prototype.createImage = HybridRenderer.prototype.createImage;
+HCompElement.prototype.createComp = HybridRenderer.prototype.createComp;
+HCompElement.prototype.createSolid = HybridRenderer.prototype.createSolid;
+HCompElement.prototype.createShape = HybridRenderer.prototype.createShape;
+HCompElement.prototype.createText = HybridRenderer.prototype.createText;
+HCompElement.prototype.createBase = HybridRenderer.prototype.createBase;
+HCompElement.prototype.appendElementInPos = HybridRenderer.prototype.appendElementInPos;
\ No newline at end of file
diff --git a/player/js/elements/htmlElements/HImageElement.js b/player/js/elements/htmlElements/HImageElement.js
index e5b9a3c..82ce022 100644
--- a/player/js/elements/htmlElements/HImageElement.js
+++ b/player/js/elements/htmlElements/HImageElement.js
@@ -6,13 +6,9 @@
 
 HImageElement.prototype.createElements = function(){
 
-    var imageLoaded = function(){
-        this.imageElem.setAttributeNS('http://www.w3.org/1999/xlink','href',assetPath);
-    };
-
+    var assetPath = this.globalData.getAssetsPath(this.assetData);
     var img = new Image();
 
-    var parent;
     if(this.data.hasMask){
         var parent = document.createElement('div');
         styleDiv(parent);
@@ -23,30 +19,25 @@
         this.imageElem = document.createElementNS(svgNS,'image');
         this.imageElem.setAttribute('width',this.assetData.w+"px");
         this.imageElem.setAttribute('height',this.assetData.h+"px");
+        this.imageElem.setAttributeNS('http://www.w3.org/1999/xlink','href',assetPath);
         cont.appendChild(this.imageElem);
         this.layerElement = parent;
-        this.appendNodeToParent(parent);
+        this.baseElement = parent;
         this.innerElem = parent;
         this.maskedElement = this.imageElem;
-        img.addEventListener('load', imageLoaded.bind(this), false);
-        img.addEventListener('error', imageLoaded.bind(this), false);
     } else {
         styleDiv(img);
         this.layerElement = img;
-        this.appendNodeToParent(img);
+        this.baseElement = img;
         this.innerElem = img;
     }
-    var assetPath = this.globalData.getAssetsPath(this.assetData);
     img.src = assetPath;
     if(this.data.ln){
         this.innerElem.setAttribute('id',this.data.ln);
     }
+    this.checkParenting();
 };
 
-
-
 HImageElement.prototype.hide = HSolidElement.prototype.hide;
-
 HImageElement.prototype.renderFrame = HSolidElement.prototype.renderFrame;
-
 HImageElement.prototype.destroy = HSolidElement.prototype.destroy;
\ No newline at end of file
diff --git a/player/js/elements/htmlElements/HShapeElement.js b/player/js/elements/htmlElements/HShapeElement.js
index 71ebb04..3b401f7 100644
--- a/player/js/elements/htmlElements/HShapeElement.js
+++ b/player/js/elements/htmlElements/HShapeElement.js
@@ -19,8 +19,6 @@
     var parent = document.createElement('div');
     styleDiv(parent);
     var cont = document.createElementNS(svgNS,'svg');
-    if(this.data.bounds.l === 999999){
-    }
     cont.setAttribute('width',this.data.bounds.r - this.data.bounds.l);
     cont.setAttribute('height',this.data.bounds.b - this.data.bounds.t);
     cont.setAttribute('viewBox',this.data.bounds.l+' '+this.data.bounds.t+' '+(this.data.bounds.r - this.data.bounds.l)+' '+(this.data.bounds.b - this.data.bounds.t));
@@ -39,7 +37,8 @@
         this.layerElement.appendChild(this.shapesContainer);
     }
     if(!this.data.hd){
-        this.parentContainer.appendChild(parent);
+        //this.parentContainer.appendChild(parent);
+        this.baseElement = parent;
     }
     this.innerElem = parent;
     if(this.data.ln){
@@ -51,6 +50,7 @@
     if(this.data.bm !== 0){
         this.setBlendMode();
     }
+    this.checkParenting();
 };
 
 HShapeElement.prototype.renderFrame = function(parentMatrix){
diff --git a/player/js/elements/htmlElements/HSolidElement.js b/player/js/elements/htmlElements/HSolidElement.js
index 50b5025..cd84eaf 100644
--- a/player/js/elements/htmlElements/HSolidElement.js
+++ b/player/js/elements/htmlElements/HSolidElement.js
@@ -11,7 +11,8 @@
     cont.setAttribute('height',this.data.sh);
     parent.appendChild(cont);
     this.layerElement = parent;
-    this.appendNodeToParent(parent);
+    //this.appendNodeToParent(parent);
+    this.baseElement = parent;
     this.innerElem = parent;
     if(this.data.ln){
         this.innerElem.setAttribute('id',this.data.ln);
@@ -27,33 +28,11 @@
     if(this.data.hasMask){
         this.maskedElement = rect;
     }
+    this.checkParenting();
 };
 
 
 
-HSolidElement.prototype.hide = function(){
-    if(!this.hidden){
-        this.innerElem.style.display = 'none';
-        this.hidden = true;
-    }
-};
-
-HSolidElement.prototype.renderFrame = function(parentMatrix){
-    var renderParent = this._parent.renderFrame.call(this,parentMatrix);
-    if(renderParent===false){
-        this.hide();
-        return;
-    }
-    if(this.hidden){
-        this.hidden = false;
-        this.innerElem.style.display = 'block';
-    }
-    if(this.firstFrame){
-        this.firstFrame = false;
-    }
-};
-
-HSolidElement.prototype.destroy = function(){
-    this._parent.destroy.call();
-    this.innerElem =  null;
-};
\ No newline at end of file
+HSolidElement.prototype.hide = IImageElement.prototype.hide;
+HSolidElement.prototype.renderFrame = IImageElement.prototype.renderFrame;
+HSolidElement.prototype.destroy = IImageElement.prototype.destroy;
\ No newline at end of file
diff --git a/player/js/elements/htmlElements/HTextElement.js b/player/js/elements/htmlElements/HTextElement.js
index 10d9c14..9bc6608 100644
--- a/player/js/elements/htmlElements/HTextElement.js
+++ b/player/js/elements/htmlElements/HTextElement.js
@@ -41,7 +41,7 @@
         this.renderType = 'html';
         this.innerElem = parent;
     }
-    this.parentContainer.appendChild(parent);
+    this.baseElement = parent;
 
     if(documentData.fc) {
         this.innerElem.style.color = this.innerElem.style.fill = 'rgb(' + Math.round(documentData.fc[0]*255) + ',' + Math.round(documentData.fc[1]*255) + ',' + Math.round(documentData.fc[2]*255) + ')';
@@ -224,7 +224,6 @@
         }
     }
     if(this.isMasked){
-
         var boundingBox = this.innerElem.getBBox();
         if(this.currentBBox.w !== boundingBox.width){
             this.currentBBox.w = boundingBox.width;
diff --git a/player/js/elements/svgElements/SVGBaseElement.js b/player/js/elements/svgElements/SVGBaseElement.js
index d0d2220..c14e55f 100644
--- a/player/js/elements/svgElements/SVGBaseElement.js
+++ b/player/js/elements/svgElements/SVGBaseElement.js
@@ -81,16 +81,19 @@
         if(this.data.tt){
             this.matteElement = document.createElementNS(svgNS,'g');
             this.matteElement.appendChild(this.layerElement);
-            this.appendNodeToParent(this.matteElement);
+            this.baseElement = this.matteElement;
+            //this.appendNodeToParent(this.matteElement);
         }else{
-            this.appendNodeToParent(this.layerElement);
+            this.baseElement = this.layerElement;
+            //this.appendNodeToParent(this.layerElement);
         }
         if(this.data.hasMask){
             this.maskedElement = this.layerElement;
         }
     }else{
         this.layerElement = document.createElementNS(svgNS,'g');
-        this.appendNodeToParent(this.layerElement);
+        this.baseElement = this.layerElement;
+        //this.appendNodeToParent(this.layerElement);
     }
     if((this.data.ln || this.data.cl) && (this.data.ty === 4 || this.data.ty === 0)){
         if(this.data.ln){
@@ -181,12 +184,13 @@
             }
         }
     }*/
+    this.checkParenting();
 };
 
 SVGBaseElement.prototype.setBlendMode = BaseElement.prototype.setBlendMode;
 
 SVGBaseElement.prototype.renderFrame = function(parentTransform){
-    if(this.data.ty === 3){
+    if(this.data.ty === 3 || this.data.hd){
         return false;
     }
 
@@ -256,8 +260,8 @@
     }
 };
 
-SVGBaseElement.prototype.getDomElement = function(){
-    return this.layerElement;
+SVGBaseElement.prototype.getBaseElement = function(){
+    return this.baseElement;
 };
 SVGBaseElement.prototype.addMasks = function(data){
     this.maskManager = new MaskElement(data,this,this.globalData);
@@ -270,6 +274,13 @@
     this.matteElement.setAttribute("mask", "url(#" + id + ")");
 };
 
+SVGBaseElement.prototype.setMatte = function(id){
+    if(!this.matteElement){
+        return;
+    }
+    this.matteElement.setAttribute("mask", "url(#" + id + ")");
+};
+
 SVGBaseElement.prototype.hide = function(){
 
 };
diff --git a/player/js/elements/svgElements/SVGTextElement.js b/player/js/elements/svgElements/SVGTextElement.js
index da50fbe..4f3a47e 100644
--- a/player/js/elements/svgElements/SVGTextElement.js
+++ b/player/js/elements/svgElements/SVGTextElement.js
@@ -37,7 +37,7 @@
 
 
 
-    var letters = documentData.l;
+    var letters = documentData.l || [];
     len = letters.length;
     if(!len){
         return;
diff --git a/player/js/renderers/BaseRenderer.js b/player/js/renderers/BaseRenderer.js
new file mode 100644
index 0000000..befe3d7
--- /dev/null
+++ b/player/js/renderers/BaseRenderer.js
@@ -0,0 +1,82 @@
+function BaseRenderer(){}
+BaseRenderer.prototype.checkLayers = function(num){
+    var i, len = this.layers.length, data;
+    this.completeLayers = true;
+    for (i = len - 1; i >= 0; i--) {
+        if (!this.elements[i]) {
+            data = this.layers[i];
+            if(data.ip - data.st <= (num - this.layers[i].st) && data.op - data.st > (num - this.layers[i].st))
+            {
+                this.buildItem(i);
+            }
+        }
+        this.completeLayers = this.elements[i] ? this.completeLayers:false;
+    }
+};
+
+BaseRenderer.prototype.createItem = function(layer){
+    switch(layer.ty){
+        case 2:
+            return this.createImage(layer);
+        case 0:
+            return this.createComp(layer);
+        case 1:
+            return this.createSolid(layer);
+        case 4:
+            return this.createShape(layer);
+        case 5:
+            return this.createText(layer);
+        case 99:
+            return null;
+    }
+    return this.createBase(layer);
+};
+BaseRenderer.prototype.buildAllItems = function(){
+    var i, len = this.layers.length;
+    for(i=0;i<len;i+=1){
+        this.buildItem(i);
+    }
+};
+
+BaseRenderer.prototype.includeLayers = function(newLayers){
+    this.completeLayers = false;
+    var i, len = newLayers.length;
+    var j, jLen = this.layers.length;
+    for(i=0;i<len;i+=1){
+        j = 0;
+        while(j<jLen){
+            if(this.layers[j].id == newLayers[i].id){
+                this.layers[j] = newLayers[i];
+                break;
+            }
+            j += 1;
+        }
+    }
+};
+
+BaseRenderer.prototype.setProjectInterface = function(pInterface){
+    this.globalData.projectInterface = pInterface;
+};
+
+BaseRenderer.prototype.initItems = function(){
+    if(!this.globalData.progressiveLoad){
+        this.buildAllItems();
+    }
+};
+BaseRenderer.prototype.buildElementParenting = function(element, parentName){
+    var elements = this.elements;
+    var layers = this.layers;
+    var i=0, len = layers.length;
+    while(i<len){
+        if(layers[i].ind == parentName){
+            if(!elements[i]){
+                this.buildItem(i);
+            }
+            element.getHierarchy().push(elements[i]);
+            if(layers[i].parent !== undefined){
+                this.buildElementParenting(element,layers[i].parent);
+            }
+        }
+        i += 1;
+    }
+};
\ No newline at end of file
diff --git a/player/js/renderers/CanvasRenderer.js b/player/js/renderers/CanvasRenderer.js
index 4d9d535..4295a7f 100644
--- a/player/js/renderers/CanvasRenderer.js
+++ b/player/js/renderers/CanvasRenderer.js
@@ -1,8 +1,9 @@
 function CanvasRenderer(animationItem, config){
     this.animationItem = animationItem;
     this.renderConfig = {
-        clearCanvas: (config && config.clearCanvas) || true,
+        clearCanvas: (config && config.clearCanvas !== undefined) ? config.clearCanvas : true,
         context: (config && config.context) || null,
+        progressiveLoad: (config && config.progressiveLoad) || false,
         preserveAspectRatio: (config && config.preserveAspectRatio) || 'xMidYMid meet'
     };
     this.renderConfig.dpr = (config && config.dpr) || 1;
@@ -26,95 +27,32 @@
     }
     this.elements = [];
     this.transformMat = new Matrix();
+    this.completeLayers = false;
 }
+extendPrototype(BaseRenderer,CanvasRenderer);
 
-CanvasRenderer.prototype.createItem = function(layer, comp, globalData){
-    switch(layer.ty){
-        case 0:
-            return this.createComp(layer, comp, globalData);
-        case 1:
-            return this.createSolid(layer, comp, globalData);
-        case 2:
-            return this.createImage(layer, comp, globalData);
-        case 4:
-            return this.createShape(layer, comp, globalData);
-        case 5:
-            return this.createText(layer, comp, globalData);
-        case 99:
-            return this.createPlaceHolder(layer, comp, globalData);
-        default:
-            return this.createBase(layer, comp, globalData);
-    }
-    return this.createBase(layer,comp, globalData);
+CanvasRenderer.prototype.createBase = function (data) {
+    return new CVBaseElement(data, this, this.globalData);
 };
 
-CanvasRenderer.prototype.buildItems = function(layers,elements, comp){
-    if(!elements){
-        elements = this.elements;
-    }
-    if(!comp){
-        comp = this;
-    }
-    var i, len = layers.length;
-    for (i = 0; i < len; i++) {
-        elements[i] = this.createItem(layers[i], comp,comp.globalData);
-        if (layers[i].ty === 0) {
-            var elems = [];
-            this.buildItems(layers[i].layers,elems,elements[i],comp.globalData);
-            elements[elements.length - 1].setElements(elems);
-        }
-    }
+CanvasRenderer.prototype.createShape = function (data) {
+    return new CVShapeElement(data, this, this.globalData);
 };
 
-CanvasRenderer.prototype.includeLayers = function(layers,parentContainer,elements){
-    var i, len = layers.length;
-    if(!elements){
-        elements = this.elements;
-    }
-    var j, jLen = elements.length, elems;
-    for(i=0;i<len;i+=1){
-        j = 0;
-        while(j<jLen){
-            if(elements[j].data.id == layers[i].id){
-                elements[j] = this.createItem(layers[i],this);
-                if (layers[i].ty === 0) {
-                    elems = [];
-                    this.buildItems(layers[i].layers,elems, elements[j]);
-                    elements[j].setElements(elems);
-                }
-                break;
-            }
-            j += 1;
-        }
-    }
+CanvasRenderer.prototype.createText = function (data) {
+    return new CVTextElement(data, this, this.globalData);
 };
 
-CanvasRenderer.prototype.createBase = function (data, comp, globalData) {
-    return new CVBaseElement(data, comp, globalData);
+CanvasRenderer.prototype.createImage = function (data) {
+    return new CVImageElement(data, this, this.globalData);
 };
 
-CanvasRenderer.prototype.createShape = function (data, comp, globalData) {
-    return new CVShapeElement(data, comp, globalData);
+CanvasRenderer.prototype.createComp = function (data) {
+    return new CVCompElement(data, this, this.globalData);
 };
 
-CanvasRenderer.prototype.createText = function (data, comp, globalData) {
-    return new CVTextElement(data, comp, globalData);
-};
-
-CanvasRenderer.prototype.createPlaceHolder = function (data, globalData) {
-    return new PlaceHolderElement(data, null,globalData);
-};
-
-CanvasRenderer.prototype.createImage = function (data, comp, globalData) {
-    return new CVImageElement(data, comp, globalData);
-};
-
-CanvasRenderer.prototype.createComp = function (data, comp, globalData) {
-    return new CVCompElement(data, comp, globalData);
-};
-
-CanvasRenderer.prototype.createSolid = function (data, comp, globalData) {
-    return new CVSolidElement(data, comp, globalData);
+CanvasRenderer.prototype.createSolid = function (data) {
+    return new CVSolidElement(data, this, this.globalData);
 };
 
 CanvasRenderer.prototype.ctxTransform = function(props){
@@ -220,6 +158,7 @@
         w: animData.w,
         h: animData.h
     };
+    this.globalData.progressiveLoad = this.renderConfig.progressiveLoad;
     this.layers = animData.layers;
     this.transformCanvas = {};
     this.transformCanvas.w = animData.w;
@@ -231,6 +170,10 @@
     this.globalData.getAssetsPath = this.animationItem.getAssetsPath.bind(this.animationItem);
     this.globalData.elementLoaded = this.animationItem.elementLoaded.bind(this.animationItem);
     this.globalData.addPendingElement = this.animationItem.addPendingElement.bind(this.animationItem);
+    this.globalData.transformCanvas = this.transformCanvas;
+    this.elements = Array.apply(null,{length:animData.layers.length});
+
+    this.updateContainerSize();
 };
 
 CanvasRenderer.prototype.updateContainerSize = function () {
@@ -272,45 +215,12 @@
     this.transformCanvas.props = [this.transformCanvas.sx,0,0,0,0,this.transformCanvas.sy,0,0,0,0,1,0,this.transformCanvas.tx,this.transformCanvas.ty,0,1];
     var i, len = this.elements.length;
     for(i=0;i<len;i+=1){
-        if(this.elements[i].data.ty === 0){
-            this.elements[i].resize(this.transformCanvas);
+        if(this.elements[i] && this.elements[i].data.ty === 0){
+            this.elements[i].resize(this.globalData.transformCanvas);
         }
     }
 };
 
-CanvasRenderer.prototype.buildStage = function (container, layers, elements) {
-    if(!elements){
-        elements = this.elements;
-    }
-    var i, len = layers.length, layerData;
-    for (i = len - 1; i >= 0; i--) {
-        layerData = layers[i];
-        if (layerData.parent !== undefined) {
-            this.buildItemHierarchy(layerData,elements[i], layers, layerData.parent,elements, true);
-        }
-        if (layerData.ty == 0) {
-            this.buildStage(null, layerData.layers, elements[i].getElements());
-        }
-    }
-    this.updateContainerSize();
-};
-
-CanvasRenderer.prototype.buildItemHierarchy = function (data,element, layers, parentName,elements,resetHierarchyFlag) {
-    var i=0, len = layers.length;
-    if(resetHierarchyFlag){
-        element.resetHierarchy();
-    }
-    while(i<len){
-        if(layers[i].ind === parentName){
-            element.getHierarchy().push(elements[i]);
-            if (layers[i].parent !== undefined) {
-                this.buildItemHierarchy(data,element, layers, layers[i].parent,elements, false);
-            }
-        }
-        i += 1;
-    }
-};
-
 CanvasRenderer.prototype.destroy = function () {
     if(this.renderConfig.clearCanvas) {
         this.animationItem.wrapper.innerHTML = '';
@@ -332,6 +242,7 @@
     this.renderedFrame = num;
     this.globalData.frameNum = num - this.animationItem.firstFrame;
     this.globalData.frameId += 1;
+    this.globalData.projectInterface.currentFrame = num;
     if(this.renderConfig.clearCanvas === true){
         this.reset();
         this.canvasContext.save();
@@ -349,11 +260,19 @@
     //console.log('--------');
     //console.log('NEW: ',num);
     var i, len = this.layers.length;
+    if(!this.completeLayers){
+        this.checkLayers(num);
+    }
+
     for (i = 0; i < len; i++) {
-        this.elements[i].prepareFrame(num - this.layers[i].st);
+        if(this.completeLayers || this.elements[i]){
+            this.elements[i].prepareFrame(num - this.layers[i].st);
+        }
     }
     for (i = len - 1; i >= 0; i-=1) {
-        this.elements[i].renderFrame();
+        if(this.completeLayers || this.elements[i]){
+            this.elements[i].renderFrame();
+        }
     }
     if(this.renderConfig.clearCanvas !== true){
         this.restore();
@@ -362,10 +281,37 @@
     }
 };
 
+CanvasRenderer.prototype.buildItem = function(pos){
+    var elements = this.elements;
+    if(elements[pos] || this.layers[pos].ty == 99){
+        return;
+    }
+    var element = this.createItem(this.layers[pos], this,this.globalData);
+    elements[pos] = element;
+    element.initExpressions();
+    if(this.layers[pos].ty === 0){
+        element.resize(this.globalData.transformCanvas);
+    }
+};
+
 CanvasRenderer.prototype.hide = function(){
     this.animationItem.container.style.display = 'none';
 };
 
 CanvasRenderer.prototype.show = function(){
     this.animationItem.container.style.display = 'block';
+};
+
+CanvasRenderer.prototype.searchExtraCompositions = function(assets){
+    var i, len = assets.length;
+    var floatingContainer = document.createElementNS(svgNS,'g');
+    for(i=0;i<len;i+=1){
+        if(assets[i].xt){
+            var comp = this.createComp(assets[i],this.globalData.comp,this.globalData);
+            comp.initExpressions();
+            //comp.compInterface = CompExpressionInterface(comp);
+            //Expressions.addLayersInterface(comp.elements, this.globalData.projectInterface);
+            this.globalData.projectInterface.registerComposition(comp);
+        }
+    }
 };
\ No newline at end of file
diff --git a/player/js/renderers/HybridRenderer.js b/player/js/renderers/HybridRenderer.js
index 8b71b66..3fa4941 100644
--- a/player/js/renderers/HybridRenderer.js
+++ b/player/js/renderers/HybridRenderer.js
@@ -9,176 +9,90 @@
     this.threeDElements = [];
     this.destroyed = false;
     this.camera = null;
+    this.supports3d = true;
 
 }
 
-HybridRenderer.prototype.createItem = function(layer,parentContainer,comp, placeholder){
-    switch(layer.ty){
-        case 2:
-            return this.createImage(layer,parentContainer,comp, placeholder);
-        case 0:
-            return this.createComp(layer,parentContainer,comp, placeholder);
-        case 1:
-            return this.createSolid(layer,parentContainer,comp, placeholder);
-        case 4:
-            return this.createShape(layer,parentContainer,comp, placeholder);
-        case 5:
-            return this.createText(layer,parentContainer,comp, placeholder);
-        case 13:
-            return this.createCamera(layer,parentContainer,comp, placeholder);
-        case 99:
-            return this.createPlaceHolder(layer,parentContainer);
+extendPrototype(BaseRenderer,HybridRenderer);
+
+HybridRenderer.prototype.buildItem = SVGRenderer.prototype.buildItem;
+
+HybridRenderer.prototype.appendElementInPos = function(element, pos){
+    var newElement = element.getBaseElement();
+    if(!newElement){
+        return;
     }
-    return this.createBase(layer,parentContainer,comp);
-};
-
-HybridRenderer.prototype.buildItems = function(layers,parentContainer,elements,comp, placeholder){
-    var  i, len = layers.length;
-    if(!elements){
-        elements = this.elements;
-    }
-    if(!comp){
-        comp = this;
-    }
-
-    var currentContainer, is3d = false;
-
-    var elems;
-
-    for (i = len - 1; i >= 0; i--) {
-        if(!parentContainer) {
-            if(layers[i].ddd) {
-                if(!is3d){
-                    is3d = true;
-                    currentContainer = this.getThreeDContainer();
-                }
-                elements[i] = this.createItem(layers[i],currentContainer,comp, placeholder);
-            } else {
-                is3d = false;
-                elements[i] = this.createItem(layers[i],this.animationItem.resizerElem,comp, placeholder);
+    var layer = this.layers[pos];
+    if(!layer.ddd || !this.supports3d){
+        var i = 0;
+        var nextElement;
+        while(i<pos){
+            if(this.elements[i] && this.elements[i].getBaseElement()){
+                nextElement = this.elements[i].getBaseElement();
             }
-        } else{
-            elements[i] = this.createItem(layers[i],parentContainer,comp, placeholder);
+            i += 1;
         }
-        if (layers[i].ty === 0) {
-            elems = [];
-            this.buildItems(layers[i].layers,elements[i].getDomElement(),elems,elements[i], elements[i].placeholder);
-            elements[i].setElements(elems);
-        }
-        if(layers[i].td){
-            elements[i+1].setMatte(elements[i].layerId);
-        }
-        //NullLayer
-    }
-    this.currentContainer = this.animationItem.resizerElem;
-    if(!parentContainer){
-        if(this.threeDElements.length){
-            if(!this.camera){
-                var cWidth = this.globalData.compSize.w;
-                var cHeight = this.globalData.compSize.h;
-                len = this.threeDElements.length;
-                for(i=0;i<len;i+=1){
-                    this.threeDElements[0][i].style.perspective = this.threeDElements[0][i].style.webkitPerspective = Math.sqrt(Math.pow(cWidth,2) + Math.pow(cHeight,2)) + 'px';
-                }
-
-            } else {
-                this.camera.setup();
+        if(nextElement){
+            if(!layer.ddd || !this.supports3d){
+                this.layerElement.insertBefore(newElement, nextElement);
+            }
+        } else {
+            if(!layer.ddd || !this.supports3d){
+                this.layerElement.appendChild(newElement);
             }
         }
+    } else {
+        this.addTo3dContainer(newElement,pos);
     }
 };
 
-HybridRenderer.prototype.includeLayers = function(layers,parentContainer,elements){
-    var i, len = layers.length;
-    if(!elements){
-        elements = this.elements;
-    }
-    if(!parentContainer){
-        parentContainer = this.currentContainer;
-    }
-    var j, jLen = elements.length, elems, placeholder;
-    for(i=0;i<len;i+=1){
-        if(!layers[i].id){
-            var elem = this.createItem(layers[i],parentContainer, this);
-            elements.push(elem);
-            if (layers[i].ty === 0) {
-                elems = [];
-                this.buildItems(layers[i].layers,elem.getDomElement(),elems, elem);
-                elem.setElements(elems);
-            }
-        }else {
-            j = 0;
-            while(j<jLen){
-                if(elements[j].data.id == layers[i].id){
-                    placeholder = elements[j];
-                    elements[j] = this.createItem(layers[i],parentContainer,this, placeholder);
-                    if (layers[i].ty === 0) {
-                        elems = [];
-                        this.buildItems(layers[i].layers,elements[j].getDomElement(),elems,elements[j], elements[i].placeholder);
-                        elements[j].setElements(elems);
-                    }
-                }
-                j += 1;
-            }
-        }
-    }
-    for(i=0;i<len;i+=1){
-        if(layers[i].td){
-            elements[i+1].setMatte(elements[i].layerId);
-        }
-    }
+
+HybridRenderer.prototype.createBase = function (data) {
+    return new SVGBaseElement(data, this.layerElement,this.globalData,this);
 };
 
-HybridRenderer.prototype.createBase = function (data,parentContainer,comp, placeholder) {
-    return new SVGBaseElement(data, parentContainer,this.globalData,comp, placeholder);
-};
-
-HybridRenderer.prototype.createPlaceHolder = function (data,parentContainer) {
-    return new PlaceHolderElement(data, parentContainer,this.globalData);
-};
-
-HybridRenderer.prototype.createShape = function (data,parentContainer,comp, placeholder) {
-    if(comp.isSvg){
-        return new IShapeElement(data, parentContainer,this.globalData,comp, placeholder);
+HybridRenderer.prototype.createShape = function (data) {
+    if(!this.supports3d){
+        return new IShapeElement(data, this.layerElement,this.globalData,this);
     }
-    return new HShapeElement(data, parentContainer,this.globalData,comp, placeholder);
+    return new HShapeElement(data, this.layerElement,this.globalData,this);
 };
 
-HybridRenderer.prototype.createText = function (data,parentContainer,comp, placeholder) {
-    if(comp.isSvg){
-        return new SVGTextElement(data, parentContainer,this.globalData,comp, placeholder);
+HybridRenderer.prototype.createText = function (data) {
+    if(!this.supports3d){
+        return new SVGTextElement(data, this.layerElement,this.globalData,this);
     }
-    return new HTextElement(data, parentContainer,this.globalData,comp, placeholder);
+    return new HTextElement(data, this.layerElement,this.globalData,this);
 };
 
-HybridRenderer.prototype.createCamera = function (data,parentContainer,comp, placeholder) {
-    this.camera = new HCameraElement(data, parentContainer,this.globalData,comp, placeholder);
+HybridRenderer.prototype.createCamera = function (data) {
+    this.camera = new HCameraElement(data, this.layerElement,this.globalData,this);
     return this.camera;
 };
 
-HybridRenderer.prototype.createImage = function (data,parentContainer,comp, placeholder) {
-    if(comp.isSvg){
-        return new IImageElement(data, parentContainer,this.globalData,comp, placeholder);
+HybridRenderer.prototype.createImage = function (data) {
+    if(!this.supports3d){
+        return new IImageElement(data, this.layerElement,this.globalData,this);
     }
-    return new HImageElement(data, parentContainer,this.globalData,comp, placeholder);
+    return new HImageElement(data, this.layerElement,this.globalData,this);
 };
 
-HybridRenderer.prototype.createComp = function (data,parentContainer,comp, placeholder) {
-    if(comp.isSvg){
-        return new ICompElement(data, parentContainer,this.globalData,comp, placeholder);
+HybridRenderer.prototype.createComp = function (data) {
+    if(!this.supports3d){
+        return new ICompElement(data, this.layerElement,this.globalData,this);
     }
-    return new HCompElement(data, parentContainer,this.globalData,comp, placeholder);
+    return new HCompElement(data, this.layerElement,this.globalData,this);
 
 };
 
-HybridRenderer.prototype.createSolid = function (data,parentContainer,comp, placeholder) {
-    if(comp.isSvg){
-        return new ISolidElement(data, parentContainer,this.globalData,comp, placeholder);
+HybridRenderer.prototype.createSolid = function (data) {
+    if(!this.supports3d){
+        return new ISolidElement(data, this.layerElement,this.globalData,this);
     }
-    return new HSolidElement(data, parentContainer,this.globalData,comp, placeholder);
+    return new HSolidElement(data, this.layerElement,this.globalData,this);
 };
 
-HybridRenderer.prototype.getThreeDContainer = function(){
+HybridRenderer.prototype.getThreeDContainer = function(pos){
     var perspectiveElem = document.createElement('div');
     styleDiv(perspectiveElem);
     perspectiveElem.style.width = this.globalData.compSize.w+'px';
@@ -188,17 +102,61 @@
     styleDiv(container);
     container.style.transform = container.style.webkitTransform = 'matrix3d(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1)';
     perspectiveElem.appendChild(container);
-    this.animationItem.resizerElem.appendChild(perspectiveElem);
-    this.threeDElements.push([perspectiveElem,container]);
-    return container;
-}
+    this.resizerElem.appendChild(perspectiveElem);
+    var threeDContainerData = {
+        container:container,
+        perspectiveElem:perspectiveElem,
+        startPos: pos,
+        endPos: pos
+    };
+    this.threeDElements.push(threeDContainerData);
+    return threeDContainerData;
+};
+
+HybridRenderer.prototype.build3dContainers = function(){
+    var i, len = this.layers.length;
+    var lastThreeDContainerData;
+    for(i=0;i<len;i+=1){
+        if(this.layers[i].ddd){
+            if(!lastThreeDContainerData){
+                lastThreeDContainerData = this.getThreeDContainer(i);
+            }
+            lastThreeDContainerData.endPos = Math.max(lastThreeDContainerData.endPos,i);
+        } else {
+            lastThreeDContainerData = null;
+        }
+    }
+};
+
+HybridRenderer.prototype.addTo3dContainer = function(elem,pos){
+    var i = 0, len = this.threeDElements.length;
+    while(i<len){
+        if(pos <= this.threeDElements[i].endPos){
+            var j = this.threeDElements[i].startPos;
+            var nextElement;
+            while(j<pos){
+                if(this.elements[j] && this.elements[j].getBaseElement()){
+                    nextElement = this.elements[j].getBaseElement();
+                }
+                j += 1;
+            }
+            if(nextElement){
+                this.threeDElements[i].container.insertBefore(elem, nextElement);
+            } else {
+                this.threeDElements[i].container.appendChild(elem);
+            }
+            break;
+        }
+        i += 1;
+    }
+};
 
 HybridRenderer.prototype.configAnimation = function(animData){
     var resizerElem = document.createElement('div');
     var wrapper = this.animationItem.wrapper;
     resizerElem.style.width = animData.w+'px';
     resizerElem.style.height = animData.h+'px';
-    this.animationItem.resizerElem = resizerElem;
+    this.resizerElem = resizerElem;
     styleDiv(resizerElem);
     resizerElem.style.transformStyle = resizerElem.style.webkitTransformStyle = resizerElem.style.mozTransformStyle = "flat";
     wrapper.appendChild(resizerElem);
@@ -208,7 +166,7 @@
     svg.setAttribute('width','1');
     svg.setAttribute('height','1');
     styleDiv(svg);
-    this.animationItem.resizerElem.appendChild(svg);
+    this.resizerElem.appendChild(svg);
     var defs = document.createElementNS(svgNS,'defs');
     svg.appendChild(defs);
     this.globalData.defs = defs;
@@ -226,47 +184,11 @@
     this.globalData.fontManager = new FontManager();
     this.globalData.fontManager.addChars(animData.chars);
     this.globalData.fontManager.addFonts(animData.fonts,svg);
+    this.layerElement = this.resizerElem;
+    this.build3dContainers();
     this.updateContainerSize();
 };
 
-HybridRenderer.prototype.buildStage = function (container, layers,elements) {
-    var i, len = layers.length, layerData;
-    if(!elements){
-        elements = this.elements;
-    }
-    for (i = len - 1; i >= 0; i--) {
-        layerData = layers[i];
-        if (layerData.parent !== undefined) {
-            this.buildItemParenting(layerData,elements[i],layers,layerData.parent,elements, true);
-        }
-
-        if (layerData.ty === 0) {
-            this.buildStage(elements[i].getComposingElement(), layerData.layers, elements[i].getElements());
-        }
-    }
-};
-HybridRenderer.prototype.buildItemParenting = function (layerData,element,layers,parentName,elements, resetHierarchyFlag) {
-    if(!layerData.parents){
-        layerData.parents = [];
-    }
-    if(resetHierarchyFlag){
-        element.resetHierarchy();
-    }
-    var i=0, len = layers.length;
-    while(i<len){
-        if(layers[i].ind == parentName){
-            element.getHierarchy().push(elements[i]);
-            if(element.data.ty === 13){
-                elements[i].finalTransform.mProp.setInverted();
-            }
-            if(layers[i].parent !== undefined){
-                this.buildItemParenting(layerData,element,layers,layers[i].parent,elements, false);
-            }
-        }
-        i += 1;
-    }
-};
-
 HybridRenderer.prototype.destroy = function () {
     this.animationItem.wrapper.innerHTML = '';
     this.animationItem.container = null;
@@ -277,6 +199,7 @@
     }
     this.elements.length = 0;
     this.destroyed = true;
+    this.animationItem = null;
 };
 
 HybridRenderer.prototype.updateContainerSize = function () {
@@ -296,35 +219,41 @@
         tx = (elementWidth-this.globalData.compSize.w*(elementHeight/this.globalData.compSize.h))/2;
         ty = 0;
     }
-    this.animationItem.resizerElem.style.transform = this.animationItem.resizerElem.style.webkitTransform = 'matrix3d(' + sx + ',0,0,0,0,'+sy+',0,0,0,0,1,0,'+tx+','+ty+',0,1)';
+    this.resizerElem.style.transform = this.resizerElem.style.webkitTransform = 'matrix3d(' + sx + ',0,0,0,0,'+sy+',0,0,0,0,1,0,'+tx+','+ty+',0,1)';
 };
 
-HybridRenderer.prototype.renderFrame = function(num){
-    if(this.renderedFrame == num || this.destroyed){
-        return;
-    }
-    if(num === null){
-        num = this.renderedFrame;
-    }else{
-        this.renderedFrame = num;
-    }
-    //console.log('-------');
-    //console.log('FRAME ',num);
-    this.globalData.frameNum = num;
-    this.globalData.frameId += 1;
-    var i, len = this.layers.length;
-    for (i = 0; i < len; i++) {
-        this.elements[i].prepareFrame(num - this.layers[i].st);
-    }
-    for (i = 0; i < len; i++) {
-        this.elements[i].renderFrame();
-    }
-};
+HybridRenderer.prototype.renderFrame = SVGRenderer.prototype.renderFrame;
 
 HybridRenderer.prototype.hide = function(){
-    this.animationItem.resizerElem.style.display = 'none';
+    this.resizerElem.style.display = 'none';
 };
 
 HybridRenderer.prototype.show = function(){
-    this.animationItem.resizerElem.style.display = 'block';
+    this.resizerElem.style.display = 'block';
 };
+
+HybridRenderer.prototype.initItems = function(){
+    this.buildAllItems();
+    if(this.camera){
+        this.camera.setup();
+    } else {
+        var cWidth = this.globalData.compSize.w;
+        var cHeight = this.globalData.compSize.h;
+        var i, len = this.threeDElements.length;
+        for(i=0;i<len;i+=1){
+            this.threeDElements[i].perspectiveElem.style.perspective = this.threeDElements[i].perspectiveElem.style.webkitPerspective = Math.sqrt(Math.pow(cWidth,2) + Math.pow(cHeight,2)) + 'px';
+        }
+    }
+};
+
+HybridRenderer.prototype.searchExtraCompositions = function(assets){
+    var i, len = assets.length;
+    var floatingContainer = document.createElement('div');
+    for(i=0;i<len;i+=1){
+        if(assets[i].xt){
+            var comp = this.createComp(assets[i],floatingContainer,this.globalData.comp,null);
+            comp.initExpressions();
+            this.globalData.projectInterface.registerComposition(comp);
+        }
+    }
+};
\ No newline at end of file
diff --git a/player/js/renderers/SVGRenderer.js b/player/js/renderers/SVGRenderer.js
index c20a629..01df78f 100644
--- a/player/js/renderers/SVGRenderer.js
+++ b/player/js/renderers/SVGRenderer.js
@@ -6,137 +6,61 @@
         frameNum: -1
     };
     this.renderConfig = {
-        preserveAspectRatio: (config && config.preserveAspectRatio) || 'xMidYMid meet'
+        preserveAspectRatio: (config && config.preserveAspectRatio) || 'xMidYMid meet',
+        progressiveLoad: (config && config.progressiveLoad) || false
     };
     this.elements = [];
     this.destroyed = false;
+
 }
 
-SVGRenderer.prototype.createItem = function(layer,parentContainer,comp, placeholder){
-    switch(layer.ty){
-        case 2:
-            return this.createImage(layer,parentContainer,comp, placeholder);
-        case 0:
-            return this.createComp(layer,parentContainer,comp, placeholder);
-        case 1:
-            return this.createSolid(layer,parentContainer,comp, placeholder);
-        case 4:
-            return this.createShape(layer,parentContainer,comp, placeholder);
-        case 5:
-            return this.createText(layer,parentContainer,comp, placeholder);
-        case 99:
-            return this.createPlaceHolder(layer,parentContainer);
-    }
-    return this.createBase(layer,parentContainer,comp);
+extendPrototype(BaseRenderer,SVGRenderer);
+
+SVGRenderer.prototype.createBase = function (data) {
+    return new SVGBaseElement(data, this.layerElement,this.globalData,this);
 };
 
-SVGRenderer.prototype.buildItems = function(layers,parentContainer,elements,comp, placeholder){
-    var  i, len = layers.length;
-    if(!elements){
-        elements = this.elements;
-    }
-    if(!parentContainer){
-        parentContainer = this.animationItem.container;
-    }
-    if(!comp){
-        comp = this;
-    }
-    var elems;
-    for (i = len - 1; i >= 0; i--) {
-        elements[i] = this.createItem(layers[i],parentContainer,comp, placeholder);
-        if (layers[i].ty === 0) {
-            elems = [];
-            this.buildItems(layers[i].layers,elements[i].getDomElement(),elems,elements[i], elements[i].placeholder);
-            elements[i].setElements(elems);
-        }
-        if(layers[i].td){
-            elements[i+1].setMatte(elements[i].layerId);
-        }
-        //NullLayer
-    }
+SVGRenderer.prototype.createShape = function (data) {
+    return new IShapeElement(data, this.layerElement,this.globalData,this);
 };
 
-SVGRenderer.prototype.includeLayers = function(layers,parentContainer,elements){
-    var i, len = layers.length;
-    if(!elements){
-        elements = this.elements;
-    }
-    if(!parentContainer){
-        parentContainer = this.animationItem.container;
-    }
-    var j, jLen = elements.length, elems, placeholder;
-    for(i=0;i<len;i+=1){
-        j = 0;
-        while(j<jLen){
-            if(elements[j].data.id == layers[i].id){
-                placeholder = elements[j];
-                elements[j] = this.createItem(layers[i],parentContainer,this, placeholder);
-                if (layers[i].ty === 0) {
-                    elems = [];
-                    this.buildItems(layers[i].layers,elements[j].getDomElement(),elems,elements[j], elements[i].placeholder);
-                    elements[j].setElements(elems);
-                }
-                break;
-            }
-            j += 1;
-        }
-    }
-    for(i=0;i<len;i+=1){
-        if(layers[i].td){
-            elements[i+1].setMatte(elements[i].layerId);
-        }
-    }
-};
-
-SVGRenderer.prototype.createBase = function (data,parentContainer,comp, placeholder) {
-    return new SVGBaseElement(data, parentContainer,this.globalData,comp, placeholder);
-};
-
-SVGRenderer.prototype.createPlaceHolder = function (data,parentContainer) {
-    return new PlaceHolderElement(data, parentContainer,this.globalData);
-};
-
-SVGRenderer.prototype.createShape = function (data,parentContainer,comp, placeholder) {
-    return new IShapeElement(data, parentContainer,this.globalData,comp, placeholder);
-};
-
-SVGRenderer.prototype.createText = function (data,parentContainer,comp, placeholder) {
-    return new SVGTextElement(data, parentContainer,this.globalData,comp, placeholder);
+SVGRenderer.prototype.createText = function (data) {
+    return new SVGTextElement(data, this.layerElement,this.globalData,this);
 
 };
 
-SVGRenderer.prototype.createImage = function (data,parentContainer,comp, placeholder) {
-    return new IImageElement(data, parentContainer,this.globalData,comp, placeholder);
+SVGRenderer.prototype.createImage = function (data) {
+    return new IImageElement(data, this.layerElement,this.globalData,this);
 };
 
-SVGRenderer.prototype.createComp = function (data,parentContainer,comp, placeholder) {
-    return new ICompElement(data, parentContainer,this.globalData,comp, placeholder);
+SVGRenderer.prototype.createComp = function (data) {
+    return new ICompElement(data, this.layerElement,this.globalData,this);
 
 };
 
-SVGRenderer.prototype.createSolid = function (data,parentContainer,comp, placeholder) {
-    return new ISolidElement(data, parentContainer,this.globalData,comp, placeholder);
+SVGRenderer.prototype.createSolid = function (data) {
+    return new ISolidElement(data, this.layerElement,this.globalData,this);
 };
 
 SVGRenderer.prototype.configAnimation = function(animData){
-    this.animationItem.container = document.createElementNS(svgNS,'svg');
-    this.animationItem.container.setAttribute('xmlns','http://www.w3.org/2000/svg');
-    this.animationItem.container.setAttribute('width',animData.w);
-    this.animationItem.container.setAttribute('height',animData.h);
-    this.animationItem.container.setAttribute('viewBox','0 0 '+animData.w+' '+animData.h);
-    this.animationItem.container.setAttribute('preserveAspectRatio',this.renderConfig.preserveAspectRatio);
-    this.animationItem.container.style.width = '100%';
-    this.animationItem.container.style.height = '100%';
-    this.animationItem.container.style.transform = 'translate3d(0,0,0)';
-    this.animationItem.container.style.transformOrigin = this.animationItem.container.style.mozTransformOrigin = this.animationItem.container.style.webkitTransformOrigin = this.animationItem.container.style['-webkit-transform'] = "0px 0px 0px";
-    this.animationItem.wrapper.appendChild(this.animationItem.container);
+    this.layerElement = document.createElementNS(svgNS,'svg');
+    this.layerElement.setAttribute('xmlns','http://www.w3.org/2000/svg');
+    this.layerElement.setAttribute('width',animData.w);
+    this.layerElement.setAttribute('height',animData.h);
+    this.layerElement.setAttribute('viewBox','0 0 '+animData.w+' '+animData.h);
+    this.layerElement.setAttribute('preserveAspectRatio',this.renderConfig.preserveAspectRatio);
+    this.layerElement.style.width = '100%';
+    this.layerElement.style.height = '100%';
+    this.layerElement.style.transform = 'translate3d(0,0,0)';
+    this.layerElement.style.transformOrigin = this.layerElement.style.mozTransformOrigin = this.layerElement.style.webkitTransformOrigin = this.layerElement.style['-webkit-transform'] = "0px 0px 0px";
+    this.animationItem.wrapper.appendChild(this.layerElement);
     //Mask animation
     var defs = document.createElementNS(svgNS, 'defs');
     this.globalData.defs = defs;
-    this.animationItem.container.appendChild(defs);
+    this.layerElement.appendChild(defs);
     this.globalData.getAssetData = this.animationItem.getAssetData.bind(this.animationItem);
     this.globalData.getAssetsPath = this.animationItem.getAssetsPath.bind(this.animationItem);
-    this.globalData.elementLoaded = this.animationItem.elementLoaded.bind(this.animationItem);
+    this.globalData.progressiveLoad = this.renderConfig.progressiveLoad;
     this.globalData.frameId = 0;
     this.globalData.compSize = {
         w: animData.w,
@@ -154,65 +78,50 @@
     maskElement.appendChild(rect);
     var maskedElement = document.createElementNS(svgNS,'g');
     maskedElement.setAttribute("clip-path", "url(#"+maskId+")");
-    this.animationItem.container.appendChild(maskedElement);
+    this.layerElement.appendChild(maskedElement);
     defs.appendChild(maskElement);
-    this.animationItem.container = maskedElement;
+    this.layerElement = maskedElement;
     this.layers = animData.layers;
     this.globalData.fontManager = new FontManager();
     this.globalData.fontManager.addChars(animData.chars);
     this.globalData.fontManager.addFonts(animData.fonts,defs);
+    this.elements = Array.apply(null,{length:animData.layers.length});
 };
 
-SVGRenderer.prototype.buildStage = function (container, layers,elements) {
-    var i, len = layers.length, layerData;
-    if(!elements){
-        elements = this.elements;
-    }
-    for (i = len - 1; i >= 0; i--) {
-        layerData = layers[i];
-        if (layerData.parent !== undefined) {
-            this.buildItemParenting(layerData,elements[i],layers,layerData.parent,elements, true);
-        }
-
-        if (layerData.ty === 0) {
-            this.buildStage(elements[i].getComposingElement(), layerData.layers, elements[i].getElements());
-        }
-    }
-};
-SVGRenderer.prototype.buildItemParenting = function (layerData,element,layers,parentName,elements, resetHierarchyFlag) {
-    if(!layerData.parents){
-        layerData.parents = [];
-    }
-    if(resetHierarchyFlag){
-        element.resetHierarchy();
-    }
-    var i=0, len = layers.length;
-    while(i<len){
-        if(layers[i].ind == parentName){
-            element.getHierarchy().push(elements[i]);
-            if(layers[i].parent !== undefined){
-                this.buildItemParenting(layerData,element,layers,layers[i].parent,elements, false);
-            }
-        }
-        i += 1;
-    }
-};
 
 SVGRenderer.prototype.destroy = function () {
     this.animationItem.wrapper.innerHTML = '';
-    this.animationItem.container = null;
+    this.layerElement = null;
     this.globalData.defs = null;
     var i, len = this.layers ? this.layers.length : 0;
     for (i = 0; i < len; i++) {
-        this.elements[i].destroy();
+        if(this.elements[i]){
+            this.elements[i].destroy();
+        }
     }
     this.elements.length = 0;
     this.destroyed = true;
+    this.animationItem = null;
 };
 
 SVGRenderer.prototype.updateContainerSize = function () {
 };
 
+SVGRenderer.prototype.buildItem  = function(pos){
+    var elements = this.elements;
+    if(elements[pos] || this.layers[pos].ty == 99){
+        return;
+    }
+    var element = this.createItem(this.layers[pos]);
+    elements[pos] = element;
+    element.initExpressions();
+    this.appendElementInPos(element,pos);
+    if(this.layers[pos].tt){
+        this.buildItem(pos - 1);
+        element.setMatte(elements[pos - 1].layerId);
+    }
+};
+
 SVGRenderer.prototype.renderFrame = function(num){
     if(this.renderedFrame == num || this.destroyed){
         return;
@@ -226,19 +135,61 @@
     console.log('FRAME ',num);*/
     this.globalData.frameNum = num;
     this.globalData.frameId += 1;
+    this.globalData.projectInterface.currentFrame = num;
     var i, len = this.layers.length;
-    for (i = len - 1; i >= 0; i--) {
-        this.elements[i].prepareFrame(num - this.layers[i].st);
+    if(!this.completeLayers){
+        this.checkLayers(num);
     }
     for (i = len - 1; i >= 0; i--) {
-        this.elements[i].renderFrame();
+        if(this.completeLayers || this.elements[i]){
+            this.elements[i].prepareFrame(num - this.layers[i].st);
+        }
+    }
+    for (i = len - 1; i >= 0; i--) {
+        if(this.completeLayers || this.elements[i]){
+            this.elements[i].renderFrame();
+        }
+    }
+};
+
+SVGRenderer.prototype.appendElementInPos = function(element, pos){
+    var newElement = element.getBaseElement();
+    if(!newElement){
+        return;
+    }
+    var i = 0;
+    var nextElement;
+    while(i<pos){
+        if(this.elements[i] && this.elements[i].getBaseElement()){
+            nextElement = this.elements[i].getBaseElement();
+        }
+        i += 1;
+    }
+    if(nextElement){
+        this.layerElement.insertBefore(newElement, nextElement);
+    } else {
+        this.layerElement.appendChild(newElement);
     }
 };
 
 SVGRenderer.prototype.hide = function(){
-    this.animationItem.container.style.display = 'none';
+    this.layerElement.style.display = 'none';
 };
 
 SVGRenderer.prototype.show = function(){
-    this.animationItem.container.style.display = 'block';
+    this.layerElement.style.display = 'block';
+};
+
+SVGRenderer.prototype.searchExtraCompositions = function(assets){
+    var i, len = assets.length;
+    var floatingContainer = document.createElementNS(svgNS,'g');
+    for(i=0;i<len;i+=1){
+        if(assets[i].xt){
+            var comp = this.createComp(assets[i],floatingContainer,this.globalData.comp,null);
+            comp.initExpressions();
+            //comp.compInterface = CompExpressionInterface(comp);
+            //Expressions.addLayersInterface(comp.elements, this.globalData.projectInterface);
+            this.globalData.projectInterface.registerComposition(comp);
+        }
+    }
 };
diff --git a/player/js/utils/DataManager.js b/player/js/utils/DataManager.js
index 046d997..8503b33 100644
--- a/player/js/utils/DataManager.js
+++ b/player/js/utils/DataManager.js
@@ -370,7 +370,7 @@
         if(jLen === 0 && !('m' in data.t.p)){
             data.singleShape = true;
         }
-        documentData.yOffset = documentData.s*1.2;
+        documentData.yOffset = documentData.lh || documentData.s*1.2;
         documentData.ascent = fontData.ascent*documentData.s/100;
     }
 
diff --git a/player/js/utils/expressions/ExpressionManager.js b/player/js/utils/expressions/ExpressionManager.js
index cb6c70e..081d77a 100644
--- a/player/js/utils/expressions/ExpressionManager.js
+++ b/player/js/utils/expressions/ExpressionManager.js
@@ -17,6 +17,21 @@
         }
     }
 
+    function $bm_neg(a){
+        var tOfA = typeof a;
+        if(tOfA === 'number' || tOfA === 'boolean'){
+            return -a;
+        }
+        if(tOfA === 'object'){
+            var i, lenA = a.length;
+            var retArr = [];
+            for(i=0;i<lenA;i+=1){
+                retArr[i] = -a[i];
+            }
+            return retArr;
+        }
+    }
+
     function sum(a,b) {
         var tOfA = typeof a;
         var tOfB = typeof b;
@@ -41,7 +56,7 @@
                 if(typeof a[i] === 'number' && typeof b[i] === 'number'){
                     retArr[i] = a[i] + b[i];
                 }else{
-                    retArr[i] = a[i] || b[i];
+                    retArr[i] = b[i] == undefined ? a[i] : a[i] || b[i];
                 }
                 i += 1;
             }
@@ -71,7 +86,7 @@
                 if(typeof a[i] === 'number' && typeof b[i] === 'number'){
                     retArr[i] = a[i] - b[i];
                 }else{
-                    retArr[i] = a[i] || b[i];
+                    retArr[i] = b[i] == undefined ? a[i] : a[i] || b[i];
                 }
                 i += 1;
             }
@@ -146,6 +161,10 @@
         return val/degToRads;
     }
 
+    function degreesToRadians(val) {
+        return val*degToRads;
+    }
+
     var helperLengthArray = [0,0,0,0,0,0];
 
     function length(arr1,arr2){
@@ -161,7 +180,6 @@
     }
 
     function rgbToHsl(val){
-        //console.log(val);
         var r = val[0]; var g = val[1]; var b = val[2];
         var max = Math.max(r, g, b), min = Math.min(r, g, b);
         var h, s, l = (max + min) / 2;
@@ -219,7 +237,7 @@
         }else if(t >= tMax){
             return value2;
         }
-        var perc = t/(tMax-tMin);
+        var perc = tMax === tMin ? 0 : t/(tMax-tMin);
         if(!value1.length){
             return value1 + (value2-value1)*perc;
         }
@@ -265,6 +283,7 @@
 
     function initiateExpression(elem,data,property){
         var val = data.x;
+        var needsVelocity = val.indexOf('velocity') !== -1;
         var elemType = elem.data.ty;
         var transform,content,effect;
         var thisComp = elem.comp;
@@ -278,7 +297,6 @@
         var bindedFn = fn.bind(this);
         var numKeys = data.k ? data.k.length : 0;
 
-
         var wiggle = function wiggle(freq,amp){
             var i,j, len = this.pv.length ? this.pv.length : 1;
             var addedAmps = Array.apply(null,{len:len});
@@ -450,6 +468,8 @@
             return this.getVelocityAtTime(t);
         }.bind(this);
 
+        var comp = elem.comp.globalData.projectInterface.bind(elem.comp.globalData.projectInterface);
+
         function effect(nm){
             return elem.effectsManager(nm);
         }
@@ -570,11 +590,10 @@
             }
             value = this.pv;
             time = this.comp.renderedFrame/this.comp.globalData.frameRate;
-            velocity = velocityAtTime(time);
-            bindedFn();
-            if(typeof this.v === 'object' && isNaN(this.v[0])){
-               // console.log(val);
+            if(needsVelocity){
+                velocity = velocityAtTime(time);
             }
+            bindedFn();
             this.frameExpressionId = elem.globalData.frameId;
             var i,len;
             if(this.mult){
@@ -591,6 +610,7 @@
                 }
             }
 
+
             if(typeof this.v === 'number'){
                 if(this.lastValue !== this.v){
                     this.lastValue = this.v;
diff --git a/player/js/utils/expressions/Expressions.js b/player/js/utils/expressions/Expressions.js
index 726d907..f757099 100644
--- a/player/js/utils/expressions/Expressions.js
+++ b/player/js/utils/expressions/Expressions.js
@@ -3,29 +3,10 @@
     ob.initExpressions = initExpressions;
     ob.getEffectsManager = getEffectsManager;
 
-    function addLayersInterface(layers){
-        var i, len = layers.length;
-        for(i=0;i<len;i+=1){
-            if(!layers[i].layerInterface){
-                layers[i].layerInterface = LayerExpressionInterface(layers[i]);
-                if(layers[i].data.hasMask){
-                    layers[i].layerInterface.registerMaskInterface(layers[i].maskManager);
-                }
-                if(layers[i].data.ty === 0){
-                    layers[i].compInterface = CompExpressionInterface(layers[i]);
-                } else if(layers[i].data.ty === 4){
-                    layers[i].layerInterface.shapeInterface = ShapeExpressionInterface.createShapeInterface(layers[i].shapesData,layers[i].viewData,layers[i].layerInterface);
-                }
-            }
-            if(layers[i].data.ty === 0){
-                addLayersInterface(layers[i].elements);
-            }
-        }
-    }
 
     function initExpressions(animation){
         animation.renderer.compInterface = CompExpressionInterface(animation.renderer);
-        addLayersInterface(animation.renderer.elements);
+        animation.renderer.globalData.projectInterface.registerComposition(animation.renderer);
     }
 
     function getEffectsManager(data,element,dynamicProperties){
diff --git a/player/js/utils/expressions/LayerInterface.js b/player/js/utils/expressions/LayerInterface.js
index 31eba90..783b05c 100644
--- a/player/js/utils/expressions/LayerInterface.js
+++ b/player/js/utils/expressions/LayerInterface.js
@@ -23,6 +23,7 @@
         function _thisLayerFunction(name){
             switch(name){
                 case "ADBE Root Vectors Group":
+                case 2:
                     return _thisLayerFunction.shapeInterface;
                     //
                     break;
diff --git a/player/js/utils/expressions/ProjectInterface.js b/player/js/utils/expressions/ProjectInterface.js
new file mode 100644
index 0000000..297133b
--- /dev/null
+++ b/player/js/utils/expressions/ProjectInterface.js
@@ -0,0 +1,29 @@
+var ProjectInterface = (function (){
+
+    function registerComposition(comp){
+        this.compositions.push(comp);
+    }
+
+    return function(){
+        function _thisProjectFunction(name){
+            var i = 0, len = this.compositions.length;
+            while(i<len){
+                if(this.compositions[i].data && this.compositions[i].data.nm === name){
+                    this.compositions[i].prepareFrame(this.currentFrame);
+                    return this.compositions[i].compInterface;
+                }
+                i+=1;
+            }
+            console.log(this.compositions);
+        }
+
+        _thisProjectFunction.compositions = [];
+        _thisProjectFunction.currentFrame = 0;
+
+        _thisProjectFunction.registerComposition = registerComposition;
+
+
+
+        return _thisProjectFunction;
+    }
+}());
\ No newline at end of file
diff --git a/player/js/utils/expressions/ShapeInterface.js b/player/js/utils/expressions/ShapeInterface.js
index 145bdcc..5bf8c9f 100644
--- a/player/js/utils/expressions/ShapeInterface.js
+++ b/player/js/utils/expressions/ShapeInterface.js
@@ -40,7 +40,7 @@
 
     function iterateElements(shapes,view, propertyGroup){
         var arr = [];
-        var i, len = shapes.length;
+        var i, len = shapes ? shapes.length : 0;
         for(i=0;i<len;i+=1){
             if(shapes[i].ty == 'gr'){
                 arr.push(ShapeExpressionInterface.createGroupInterface(shapes[i],view[i],propertyGroup));
@@ -51,7 +51,7 @@
             }else if(shapes[i].ty == 'tm'){
                 arr.push(ShapeExpressionInterface.createTrimInterface(shapes[i],view[i],propertyGroup));
             }else if(shapes[i].ty == 'tr'){
-                arr.push(ShapeExpressionInterface.createTransformInterface(shapes[i],view[i],propertyGroup));
+                //arr.push(ShapeExpressionInterface.createTransformInterface(shapes[i],view[i],propertyGroup));
             }else if(shapes[i].ty == 'el'){
                 arr.push(ShapeExpressionInterface.createEllipseInterface(shapes[i],view[i],propertyGroup));
             }else if(shapes[i].ty == 'sr'){
@@ -67,18 +67,14 @@
 
     var shapeInterfaceFactory = (function(){
         return function(shapes,view,propertyGroup){
-            //console.log('shapes',shapes);
-            // console.log('view',view);
             var interfaces;
             function _interfaceFunction(value){
-                //console.log('shapeInterfaceFactory::value: ',value);
                 if(typeof value === 'number'){
                     return interfaces[value-1];
                 } else {
                     var i = 0, len = interfaces.length;
                     while(i<len){
                         if(interfaces[i]._name === value){
-                            //console.log('interfaces[i]: ',interfaces[i]);
                             return interfaces[i];
                         }
                         i+=1;
@@ -91,13 +87,49 @@
         }
     }());
 
+    var contentsInterfaceFactory = (function(){
+       return function(shape,view, propertyGroup){
+           var interfaces;
+           var interfaceFunction = function _interfaceFunction(value){
+               if(typeof value === 'number'){
+                   return interfaces[value-1];
+               }
+               var i = 0, len = interfaces.length;
+               while(i<len){
+                   if(interfaces[i]._name === value){
+                       return interfaces[i];
+                   }
+                   i+=1;
+               }
+           };
+           interfaceFunction.propertyGroup = function(val){
+               if(val === 1){
+                   return interfaceFunction;
+               } else{
+                   return propertyGroup(val-1);
+               }
+           };
+
+           interfaces = iterateElements(shape.it, view.it, interfaceFunction.propertyGroup);
+
+           return interfaceFunction;
+       }
+    }());
+
     var groupInterfaceFactory = (function(){
         return function(shape,view, propertyGroup){
-            var interfaces;
             var interfaceFunction = function _interfaceFunction(value){
-                if(value === 'ADBE Vectors Group'){
-                    return interfaceFunction;
-                } else if(value === 'ADBE Vector Transform Group'){
+                switch(value){
+                    case 'ADBE Vectors Group':
+                    case 2:
+                        return interfaceFunction.content;
+                    case 'ADBE Vector Transform Group':
+                    case 3:
+                    default:
+                        return interfaceFunction.transform;
+                }
+                /*if(value === 'ADBE Vector Transform Group'){
+                    return interfaceFunction.transform;
                     var i = 0, len = interfaces.length;
                     while(i<len){
                         if(interfaces[i].ty === 'tr'){
@@ -117,7 +149,7 @@
                         }
                         i+=1;
                     }
-                }
+                }*/
             }
             interfaceFunction.propertyGroup = function(val){
                 if(val === 1){
@@ -126,14 +158,16 @@
                     return propertyGroup(val-1);
                 }
             };
-            interfaces = iterateElements(shape.it, view.it, interfaceFunction.propertyGroup);
+            var content = contentsInterfaceFactory(shape,view,interfaceFunction.propertyGroup);
+            var transformInterface = ShapeExpressionInterface.createTransformInterface(shape.it[shape.it.length - 1],view.it[view.it.length - 1],interfaceFunction.propertyGroup);
+            interfaceFunction.content = content;
+            interfaceFunction.transform = transformInterface;
             Object.defineProperty(interfaceFunction, '_name', {
                 get: function(){
                     return shape.nm;
                 }
             });
-            //interfaceFunction.name = shape.nm;
-            interfaceFunction.content = interfaceFunction;
+            //interfaceFunction.content = interfaceFunction;
             interfaceFunction.nm = shape.nm;
             return interfaceFunction;
         }
@@ -141,6 +175,7 @@
 
     var fillInterfaceFactory = (function(){
         return function(shape,view,propertyGroup){
+
             view.c.setGroupProperty(propertyGroup);
             view.o.setGroupProperty(propertyGroup);
             var ob = {
@@ -164,9 +199,16 @@
 
     var strokeInterfaceFactory = (function(){
         return function(shape,view,propertyGroup){
-            view.c.setGroupProperty(propertyGroup);
-            view.o.setGroupProperty(propertyGroup);
-            view.w.setGroupProperty(propertyGroup);
+            function _propertyGroup(val){
+                if(val === 1){
+                    return ob;
+                } else{
+                    return propertyGroup(val-1);
+                }
+            };
+            view.c.setGroupProperty(_propertyGroup);
+            view.o.setGroupProperty(_propertyGroup);
+            view.w.setGroupProperty(_propertyGroup);
             var ob = {
                 get color(){
                     if(view.c.k){
@@ -210,7 +252,7 @@
         return function(shape,view,propertyGroup){
             function _propertyGroup(val){
                 if(val == 1){
-                    return _propertyGroup;
+                    return interfaceFunction;
                 } else {
                     return propertyGroup(--val);
                 }
@@ -232,6 +274,7 @@
                     return interfaceFunction.offset;
                 }
             }
+            interfaceFunction.propertyIndex = shape.ix;
             Object.defineProperty(interfaceFunction, 'start', {
                 get: function(){
                     if(view.s.k){
@@ -269,7 +312,7 @@
         return function(shape,view,propertyGroup){
             function _propertyGroup(val){
                 if(val == 1){
-                    return _propertyGroup;
+                    return interfaceFunction;
                 } else {
                     return propertyGroup(--val);
                 }
@@ -314,7 +357,7 @@
                     if(view.transform.mProps.o.k){
                         view.transform.mProps.o.getValue();
                     }
-                    return view.transform.mProps.o.v;
+                    return view.transform.mProps.o.v/view.transform.mProps.o.mult;
                 }
             });
             Object.defineProperty(interfaceFunction, 'position', {
diff --git a/player/js/utils/imagePreloader.js b/player/js/utils/imagePreloader.js
new file mode 100644
index 0000000..3a752e6
--- /dev/null
+++ b/player/js/utils/imagePreloader.js
@@ -0,0 +1,60 @@
+var ImagePreloader = (function(){
+
+    function imageLoaded(){
+        this.loadedAssets += 1;
+        if(this.loadedAssets === this.totalImages){
+        }
+    }
+
+    function getAssetsPath(assetData){
+        var path = '';
+        if(this.assetsPath){
+            var imagePath = assetData.p;
+            if(imagePath.indexOf('images/') !== -1){
+                imagePath = imagePath.split('/')[1];
+            }
+            path = this.assetsPath + imagePath;
+        } else {
+            path = this.path;
+            path += assetData.u ? assetData.u : '';
+            path += assetData.p;
+        }
+        return path;
+    }
+
+    function loadImage(path){
+        var img = document.createElement('img');
+        img.addEventListener('load', imageLoaded.bind(this), false);
+        img.addEventListener('error', imageLoaded.bind(this), false);
+        img.src = path;
+    }
+    function loadAssets(assets){
+        this.totalAssets = assets.length;
+        var i;
+        for(i=0;i<this.totalAssets;i+=1){
+            if(!assets[i].layers){
+                loadImage.bind(this)(getAssetsPath.bind(this)(assets[i]));
+                this.totalImages += 1;
+            }
+        }
+    }
+
+    function setPath(path){
+        this.path = path || '';
+    }
+
+    function setAssetsPath(path){
+        this.assetsPath = path || '';
+    }
+
+    return function ImagePreloader(){
+        this.loadAssets = loadAssets;
+        this.setAssetsPath = setAssetsPath;
+        this.setPath = setPath;
+        this.assetsPath = '';
+        this.path = '';
+        this.totalAssets = 0;
+        this.totalImages = 0;
+        this.loadedAssets = 0;
+    }
+}());
\ No newline at end of file