update for darken/lighten

This commit is contained in:
jdescottes 2014-05-17 00:04:55 +02:00
parent db9e832984
commit e9a5e27266
124 changed files with 2558 additions and 23266 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,8 +0,0 @@
.tooltip.in {
opacity: 0.95;
filter: alpha(opacity=95);
}
.tooltip {
line-height: 20px;
}

View File

@ -1,112 +0,0 @@
/*!
* Bootstrap v2.1.1
*
* Copyright 2012 Twitter, Inc
* Licensed under the Apache License v2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Designed and built with all the love in the world @twitter by @mdo and @fat.
*/
.clearfix {
*zoom: 1;
}
.clearfix:before,
.clearfix:after {
display: table;
content: "";
line-height: 0;
}
.clearfix:after {
clear: both;
}
.hide-text {
font: 0/0 a;
color: transparent;
text-shadow: none;
background-color: transparent;
border: 0;
}
.input-block-level {
display: block;
width: 100%;
min-height: 30px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.tooltip {
position: absolute;
z-index: 1030;
display: block;
visibility: visible;
padding: 5px;
font-size: 11px;
opacity: 0;
filter: alpha(opacity=0);
}
.tooltip.in {
opacity: 0.8;
filter: alpha(opacity=80);
}
.tooltip.top {
margin-top: -3px;
}
.tooltip.right {
margin-left: 3px;
}
.tooltip.bottom {
margin-top: 3px;
}
.tooltip.left {
margin-left: -3px;
}
.tooltip-inner {
max-width: 200px;
padding: 3px 8px;
color: #ffffff;
text-align: center;
text-decoration: none;
background-color: #000000;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
.tooltip-arrow {
position: absolute;
width: 0;
height: 0;
border-color: transparent;
border-style: solid;
}
.tooltip.top .tooltip-arrow {
bottom: 0;
left: 50%;
margin-left: -5px;
border-width: 5px 5px 0;
border-top-color: #000000;
}
.tooltip.right .tooltip-arrow {
top: 50%;
left: 0;
margin-top: -5px;
border-width: 5px 5px 5px 0;
border-right-color: #000000;
}
.tooltip.left .tooltip-arrow {
top: 50%;
right: 0;
margin-top: -5px;
border-width: 5px 0 5px 5px;
border-left-color: #000000;
}
.tooltip.bottom .tooltip-arrow {
top: 0;
left: 50%;
margin-left: -5px;
border-width: 0 5px 5px;
border-bottom-color: #000000;
}
.tooltip {
line-height: 20px;
}

View File

@ -1 +0,0 @@
Bootstrap custom build containing only the tooltip component

View File

@ -1,108 +0,0 @@
.cheatsheet-link {
position: fixed;
bottom: 10px;
left: 10px;
padding: 1px 0 0 45px;
color : gold;
font-weight: bold;
font-size : 1.25em;
line-height: 20px;
cursor : pointer;
background-image:url('../img/keyboard.png');
background-size:35px 20px;
background-repeat:no-repeat;
opacity: 0.5;
z-index: 11000;
transition : opacity 0.3s;
}
.cheatsheet-link:hover {
opacity: 1;
}
#cheatsheet-wrapper {
position: absolute;
z-index: 10000;
top: 0;
right: 0;
bottom: 0;
left: 0;
padding: 50px;
box-sizing: border-box;
-moz-box-sizing : border-box;
color: white;
}
.cheatsheet-container {
width: 100%;
height: 100%;
box-sizing: border-box;
-moz-box-sizing : border-box;
padding: 20px 3%;
border-radius: 3px;
background: rgba(0,0,0,0.9);
overflow: auto;
}
.cheatsheet-container h3 {
font-size:24px;
margin-top: 0;
}
.cheatsheet-section {
float: left;
width : 33%;
}
.cheatsheet-shortcut {
overflow: hidden;
margin: 10px 0;
}
.cheatsheet-icon.tool-icon {
float: left;
display: inline-block;
height: 30px;
width: 30px;
margin: 0 20px 0 0;
background-size: 20px 20px;
background-position: 5px 5px;
}
.cheatsheet-description {
font-family:Courier;
color: white;
font-size : 13px;
margin-left: 20px;
line-height : 30px;
}
.cheatsheet-key {
display : inline-block;
height: 30px;
line-height: 30px;
padding: 0 10px;
border : 1px solid gold;
border-radius: 2px;
box-sizing: border-box;
-moz-box-sizing : border-box;
text-align: center;
font-family:Courier;
font-weight: bold;
font-size : 18px;
color: gold;
}

View File

@ -1,30 +0,0 @@
#dialog-container-wrapper {
position: absolute;
z-index: 20000;
top: 0;
right: 0;
bottom: 0;
left: 0;
padding: 50px 150px;
box-sizing: border-box;
-moz-box-sizing : border-box;
color: white;
background: rgba(0,0,0,0.5);
display : none;
}
#dialog-container {
width: 100%;
height: 100%;
box-sizing: border-box;
-moz-box-sizing : border-box;
border-radius: 3px;
background: rgba(0,0,0,0.9);
overflow: auto;
}

View File

@ -1,227 +0,0 @@
.palette-manager-wrapper {
height: 100%;
position: relative;
}
.palette-manager-body {
position: absolute;
top: 45px;
bottom: 0;
right: 0;
left: 0;
}
.palette-manager-head {
position: absolute;
width: 100%;
background: gold;
margin: 0;
padding: 10px;
color: black;
font-size: 1.8em;
box-sizing: border-box;
-moz-box-sizing: border-box;
}
.palette-manager-close {
position: absolute;
top: 0;
right: 0;
line-height: 45px;
margin-right: 10px;
font-size: 1.3em;
cursor: pointer;
}
.palette-manager-drawer {
width: 200px;
position: absolute;
top: 0;
bottom: 0;
}
.palette-manager-list {
position: absolute;
top:40px;
right: 0;
bottom: 0;
left: 0;
overflow: auto;
}
.palette-manager-actions {
position: absolute;
height:40px;
line-height:40px;
width: 100%;
text-align: center;
}
.palette-manager-actions-button {
width: 80px;
margin: 5px;
}
.palette-manager-palette-button,
.palette-manager-actions-button {
line-height: 20px;
}
.palette-manager-list li {
height: 48px;
line-height: 48px;
padding-left:10px;
font-size: 1.4em;
box-sizing: border-box;
-moz-box-sizing: border-box;
border-bottom: 1px solid #666;
cursor:pointer;
}
.palette-manager-list li:hover {
background : #222;
}
.palette-manager-list li.selected {
color : gold;
font-weight: bold;
}
.palette-manager-list li:nth-child(1) {
border-top: 1px solid #666;
}
.palette-manager-details {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 200px;
box-sizing: border-box;
-moz-box-sizing: border-box;
border-left:1px solid #666;
}
.palette-manager-details-head {
position: absolute;
height:40px;
line-height:40px;
width: 100%;
box-sizing: border-box;
-moz-box-sizing: border-box;
}
.palette-manager-details-head-name {
padding: 0 10px 0 20px;
font-size: 1.5em;
font-weight: bold;
}
.palette-manager-details-head-edit-icon {
cursor: pointer;
width: 24px;
height: 100%;
background: url('../../img/tools/pen.png');
display: inline-block;
background-size: 20px;
background-repeat: no-repeat;
background-position: 50%;
}
.palette-manager-details-head-actions {
float: right;
line-height: 40px;
padding-right: 10px;
}
.palette-manager-details-body {
position: absolute;
top:40px;
right: 0;
bottom: 0;
left: 0;
overflow: auto;
box-sizing: border-box;
-moz-box-sizing: border-box;
}
.palette-manager-color-card {
width: 120px;
height: 180px;
display: inline-block;
position: relative;
margin: 20px 0 20px 20px;
box-shadow: 0 0 0px 0px gold;
transition: box-shadow 0.3s;
}
.palette-manager-color-card:hover {
box-shadow: 0 0 4px 1px gold;
}
.palette-manager-delete-card {
position: absolute;
top: 0;
right: 0;
width: 20px;
text-align: center;
font-size: 1.6em;
font-weight: bold;
color: rgb(255,255,255);
text-shadow : 0 0 2px rgb(0,0,0);
cursor: pointer;
opacity : 0.2;
transition : opacity 0.3s, color 0.1s;
}
.palette-manager-color-card:hover .palette-manager-delete-card {
opacity : 0.6;
}
.palette-manager-color-card .palette-manager-delete-card:hover {
opacity : 1;
color: rgb(240,80,80);
}
.palette-manager-new-color .palette-manager-color-square {
border: 3px dotted #888;
border-bottom-width: 0;
box-sizing: border-box;
-moz-box-sizing: border-box;
border-radius: 3px 3px 0 0;
cursor: pointer;
text-align: center;
font-size: 24px;
color: #888;
line-height: 120px;
}
.palette-manager-color-square {
width: 120px;
height: 120px;
cursor: pointer;
/*background-image:url(../../img/tools/eyedropper.png);*/
}
.palette-manager-color-details {
color : #666;
background: #eee;
height: 60px;
padding-left: 5px;
}
.palette-manager-color-details li{
line-height: 20px;
font-weight: bold;
}

View File

@ -1,76 +0,0 @@
.row {
display: block;
}
.textfield {
background : black;
border : 1px solid #888;
border-radius : 2px;
padding : 3px 10px;
color : white;
box-sizing:border-box;
-moz-box-sizing:border-box;
}
.textfield[disabled=disabled] {
background : #3a3a3a;
}
.textfield-small {
width : 50px;
}
.button {
height: 24px;
box-sizing: border-box;
background-color: #3f3f3f;
border: 1px solid #333;
border-top-color: #666;
border-bottom-color: #222;
cursor: pointer;
text-decoration: none;
color: white;
text-shadow: 0px -1px 0 black;
font-weight: bold;
font-size: 1rem;
text-align: center;
transition: background-color 0.2s linear;
}
.button:hover {
text-decoration: none;
background-color: #484848;
color: gold;
}
.button-primary {
background-color: rgb(255,215,0); /* gold */
border-color: rgb(179, 164, 0);
border-top-color: white;
border-bottom-color: rgb(151, 133, 0);
color: black;
text-shadow: 0px 1px 0 #fff;
}
.button-primary:hover {
background-color: rgb(255,235,20);
color: #333;
}
.button[disabled],
.button[disabled]:hover {
cursor:default;
background-color: #aaa;
color: #777;
text-shadow: 0px 1px 0 #bbb;
border-color: #666;
border-top-color: #999;
border-bottom-color: #555;
}

View File

@ -1,8 +0,0 @@
.minimap-crop-frame {
position:absolute;
border:1px solid rgba(255,255,255,0.5);
z-index:9999;
box-sizing : border-box;
-moz-box-sizing : border-box;
cursor : pointer;
}

View File

@ -96,6 +96,8 @@ body {
.right-column {
vertical-align: top;
margin-left: 10px;
height: 100%;
position: relative;
}
.drawing-canvas-container {
@ -212,6 +214,24 @@ body {
border : 0px Solid transparent;
}
#animated-preview-container {
background: #333;
border-radius : 0 0 2px 2px;
overflow : hidden;
}
#animated-preview-canvas-container {
height :200px;
width : 200px;
}
.tiled-frame-container {
height: 100%;
width: 100%;
position: relative;
background-repeat : repeat;
}
.display-fps {
float: left;
color: #aaa;
@ -224,6 +244,8 @@ body {
.range-fps {
overflow: hidden;
width: 120px;
height : 24px;
margin : 0;
}
/**
@ -263,6 +285,36 @@ body {
.image-link {
color : gold;
}
.pull-top,
.pull-right,
.pull-bottom,
.pull-left {
position:absolute;
}
.pull-top {
top:0;
}
.pull-right {
right:0;
}
.pull-bottom {
bottom:0;
}
.pull-left {
left:0;
}
.cursor-coordinates {
color:#888;
font-size:12px;
font-weight:bold;
font-family:Courier;
}
.row {
display: block;
}
@ -362,9 +414,9 @@ body {
margin-right: 0;
}
/*
* Settings icons
*/
/********************************************************** *j* j** j*j j j j** *****************/
/* Settings icons I I I I I\I \ */
/********************************************************** *** *** *** * * '** *****************/
.tool-icon.gallery-icon {
background-image: url(../img/gallery.png);
@ -445,6 +497,10 @@ body {
border-left : 3px solid gold;
}
/************************************************************************************************/
/* Common settings classes */
/************************************************************************************************/
.settings-section {
margin: 10px 20px;
font-size: 12px;
@ -465,13 +521,26 @@ body {
padding-bottom: 5px;
}
.settings-description {
margin : 0 0 10px 0;
display : inline-block;
}
.settings-form-section {
margin-bottom: 10px;
}
.settings-item {
margin : 10px 0;
}
/************************************************************************************************/
/* Application settings */
/************************************************************************************************/
.background-picker-wrapper {
overflow: hidden;
padding: 10px 5px 20px 5px;
padding: 5px;
}
.background-picker {
@ -502,11 +571,12 @@ body {
border: gold 1px solid;
}
/* Gif/Png Export Setting panel*/
/*******************************/
/************************************************************************************************/
/* Gif/Png Export panel */
/************************************************************************************************/
.gif-upload-button,
.gif-render-button {
/*float : right;*/
margin-top : 10px;
margin-right : 10px;
}
@ -515,6 +585,17 @@ body {
margin:10px 0;
}
.gif-export-progress-status {
margin-left: 5px;
}
.gif-export-progress-bar {
margin-top:5px;
height:3px;
width: 0;
background:gold;
}
.gif-export-preview,
.png-export-preview {
margin-top:20px;
@ -549,7 +630,10 @@ body {
color: white;
}
/* Import panel */
/************************************************************************************************/
/* Import panel */
/************************************************************************************************/
.import-section,
.resize-section {
margin: 15px 0;
@ -627,6 +711,11 @@ body {
vertical-align: middle;
}
/************************************************************************************************/
/* Browse local piskels panel */
/************************************************************************************************/
.local-piskels-list {
width: 100%;
}
@ -663,6 +752,7 @@ body {
}
.tool-icon {
position : relative;
cursor : pointer;
width: 46px;
height: 46px;
@ -676,10 +766,16 @@ body {
.tool-icon.selected {
cursor: default;
background-color: #444;
}
.tool-icon.selected:before {
content:"";
position : absolute;
height : 100%;
width : 100%;
border: 3px solid gold;
box-sizing: border-box;
-moz-box-sizing: border-box;
background-position: 9px 9px;
}
.tool-icon:hover {
@ -699,10 +795,6 @@ body {
background-size: 38px 27px;
}
.tool-icon.tool-vertical-mirror-pen.selected {
background-position: -3px 7px;
}
.tool-icon.tool-paint-bucket {
background-image: url(../img/tools/paintbucket.png);
}
@ -736,15 +828,16 @@ body {
background-size: 24px 20px;
}
.tool-icon.tool-rectangle.selected,
.tool-icon.tool-rectangle-select.selected {
background-position: 9px 11px;
}
.tool-icon.tool-shape-select {
background-image: url(../img/tools/magicwand.png);
}
.tool-icon.tool-lighten {
background-image: url(../img/tools/lighten.png);
background-size: 30px 30px;
background-position: 8px 8px;
}
.tool-icon.tool-colorpicker {
background-image: url(../img/tools/eyedropper.png);
background-size: 23px 23px;
@ -762,7 +855,8 @@ body {
cursor: url(../img/icons/vertical-mirror-pen.png) 5 15, pointer;
}
.tool-pen .drawing-canvas-container:hover {
.tool-pen .drawing-canvas-container:hover,
.tool-lighten .drawing-canvas-container:hover {
cursor: url(../img/icons/pen.png) 0 15, pointer;
}
@ -787,7 +881,7 @@ body {
}
.tool-rectangle-select .drawing-canvas-container:hover {
cursor: url(../img/icons/select.png) 15 15, pointer;
cursor: crosshair;
}
.tool-shape-select .drawing-canvas-container:hover {
@ -824,7 +918,7 @@ body {
.tool-color-picker:nth-child(2) {
z-index : 90;
margin-top: 20px;
margin-top: 25px;
margin-left:-20px;
}
@ -882,6 +976,16 @@ body {
.action-icon {
cursor: pointer;
height: 100%;
background-repeat: no-repeat;
background-position: 50%;
}
.action-icon.edit-icon {
background-image: url('../img/tools/pen.png');
}
.cheatsheet-link {
position: fixed;
bottom: 10px;
@ -1032,7 +1136,7 @@ body {
-moz-box-sizing : border-box;
border-radius: 3px;
background: rgba(0,0,0,0.9);
background: rgba(0,0,0,1);
overflow: auto;
}
@ -1166,15 +1270,10 @@ body {
font-weight: bold;
}
.palette-manager-details-head-edit-icon {
cursor: pointer;
.palette-manager-details-head .edit-icon {
width: 24px;
height: 100%;
background: url('../img/tools/pen.png');
display: inline-block;
background-size: 20px;
background-repeat: no-repeat;
background-position: 50%;
background-size: 16px;
}
.palette-manager-details-head-actions {
@ -1274,7 +1373,9 @@ body {
color: white;
text-align: left;
border-radius: 4px;
margin-top: 10px;
margin-top: 5px;
margin-bottom: 10px;
overflow: hidden;
}
.toolbox-title {
@ -1323,11 +1424,27 @@ body {
.layer-item {
height:24px;
line-height: 24px;
padding : 0 10px;
padding : 0 0 0 10px;
border-top: 1px solid #444;
cursor : pointer;
}
.layer-item .edit-icon {
float: right;
width: 30px;
background-size: 12px;
opacity: 0;
transition : opacity 0.2s;
}
.layer-item:hover .edit-icon {
opacity : 0.6;
}
.layer-item:hover .edit-icon:hover {
opacity : 1;
}
.layer-item:hover {
background : #222;
}
@ -1342,9 +1459,6 @@ body {
font-family : 'Lucida Grande', Calibri;
padding : 2px 6px 0 6px;
}
.palettes-list-container {
}
.palettes-list-select {
float:right;
max-width:90px;
@ -1358,7 +1472,8 @@ body {
}
.palettes-list-colors {
overflow:hidden;
overflow: auto;
max-height: 160px;
}
.palettes-list-color {
@ -1379,8 +1494,13 @@ body {
height : 32px;
}
.palettes-list-color.primary:before,
.palettes-list-color.secondary:before {
.palettes-list-has-scrollbar .palettes-list-color,
.palettes-list-has-scrollbar .palettes-list-color div{
width: 29px
}
.palettes-list-primary-color:before,
.palettes-list-secondary-color:before {
content: "";
position: absolute;
bottom: 1px;
@ -1392,13 +1512,13 @@ body {
height: 0px;
}
.palettes-list-color.primary:before {
.palettes-list-primary-color:before {
left: 1px;
border-right-color: transparent;
}
.palettes-list-color.secondary:before {
.palettes-list-secondary-color:before {
right: 1px;
border-left-color: transparent;
}
@ -2137,7 +2257,7 @@ See http://bgrins.github.io/spectrum/themes/ for instructions.
position: absolute;
left: 0;
right: 12px;
-webkit-transition: all 500ms ease-out;
-moz-transition: all 500ms ease-out;
-ms-transition: all 500ms ease-out;
@ -2205,6 +2325,8 @@ See http://bgrins.github.io/spectrum/themes/ for instructions.
border: #444 3px solid;
border-radius: 3px;
margin: 5px 0;
width: 96px;
height: 96px;
}
.preview-tile:first-child {

View File

@ -1,185 +0,0 @@
.preview-list-wrapper {
position: relative;
height: 100%;
overflow: hidden;
}
.preview-list-scroller {
overflow-y: scroll;
overflow-x: hidden;
height: 100%;
}
.top-overflow,
.bottom-overflow {
height: 20px;
position: absolute;
left: 0;
right: 12px;
-webkit-transition: all 500ms ease-out;
-moz-transition: all 500ms ease-out;
-ms-transition: all 500ms ease-out;
-o-transition: all 500ms ease-out;
transition: all 500ms ease-out;
background-image: linear-gradient(45deg, rgba(0,0,0, 0.8) 25%, transparent 25%, transparent 75%, rgba(0,0,0, 0.8) 75%, rgba(0,0,0, 0.8)),
linear-gradient(-45deg, rgba(0,0,0, 0.8) 25%, transparent 25%, transparent 75%, rgba(0,0,0, 0.8) 75%, rgba(0,0,0, 0.8));
background-size: 29px 45px;
background-repeat: repeat-x;
background-position-x: 3px;
z-index: 10;
}
.top-overflow {
top: -20px;
}
.bottom-overflow {
bottom: -20px;
background-position-x: 0;
background-position-y: -23px;
}
.top-overflow-visible .top-overflow {
top: 0;
}
.bottom-overflow-visible .bottom-overflow {
bottom: 0;
}
.preview-list {
list-style-type: none;
padding-right: 7px;
}
.add-frame-action {
border: #888 solid 4px;
font-size: 13px;
color: #888;
cursor: pointer;
padding: 6px 0;
border-radius: 4px;
margin-top: 8px;
background-image: url(../img/plus.png);
background-repeat: no-repeat;
background-position: 3px 7px;
background-size: 26px 26px;
text-indent: 18px;
background-color: #222;
}
.add-frame-action .label {
width: 80px;
margin: 0 auto;
}
.add-frame-action:hover {
border-color: gold;
}
.preview-tile {
position: relative;
border: #444 3px solid;
border-radius: 3px;
margin: 5px 0;
}
.preview-tile:first-child {
margin-top: 0;
}
.preview-tile:hover {
border: #999 3px solid;
}
.preview-tile .tile-overlay {
z-index: 10;
position: absolute;
background-color: rgba(100, 100, 100, 0.6);
opacity: 0;
height: 30px;
width: 30px;
border: none;
}
.preview-tile:hover .tile-overlay {
opacity: 1.0;
}
.preview-tile .tile-overlay.tile-count {
display: block;
opacity: 1.0;
border-bottom-right-radius: 3px;
top: 0;
left: 0;
font-size: 14px;
line-height: 30px;
color: white;
font-weight: bold;
text-align: center;
cursor: default;
}
.preview-tile .tile-overlay.delete-frame-action {
background-image: url(../img/garbage.png);
background-repeat: no-repeat;
top: 0;
right: 0;
border-bottom-left-radius: 3px;
height: 30px;
width: 30px;
background-position: 5px 5px;
background-size: 20px;
cursor: pointer;
}
.preview-tile .tile-overlay.duplicate-frame-action {
bottom: 0;
right: 0;
border-bottom-left-radius: 3px;
background-image: url(../img/duplicate.png);
background-repeat: no-repeat;
background-position: 5px 5px;
background-size: 20px;
cursor: pointer;
}
.preview-tile .tile-overlay.dnd-action {
bottom: 0;
left: 0;
border-top-right-radius: 3px;
background-image: url(../img/dragndrop.png);
background-repeat: no-repeat;
background-position: 5px 5px;
background-size: 20px;
cursor: move;
}
.preview-tile.selected {
border-color: gold;
}
.preview-tile.selected:after {
content: " ";
position: absolute;
top: 38px;
right: -15px;
border: transparent 4px solid;
border-left-color: gold;
border-width: 6px;
border-style: solid;
}
/**
* Drag n drop styles.
*/
.preview-tile-drop-proxy {
border: 3px dashed gold;
height: 90px;
border-radius: 9px;
background-color: rgba(255, 215,0, 0.2);
}

View File

@ -1,36 +0,0 @@
html, body {
height : 100%; width: 100%;
margin : 0;
overflow: hidden;
cursor : default;
font-family: arial;
font-size: 11px;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
ul, li {
margin : 0;
padding : 0;
list-style-type: none;
}
/* Force apparition of scrollbars on leopard */
::-webkit-scrollbar {
-webkit-appearance: none;
width: 6px;
}
::-webkit-scrollbar-thumb {
border-radius: 2px;
background-color: #666;
}
::-webkit-scrollbar-track {
background-color: rgba(50, 50, 50, 0.4);
}

View File

@ -1,316 +0,0 @@
/** Righty sticky drawer expanded state. */
.right-sticky-section.sticky-section {
right: 0;
width: 47px;
-webkit-transition: all 200ms ease-out;
-moz-transition: all 200ms ease-out;
-ms-transition: all 200ms ease-out;
-o-transition: all 200ms ease-out;
transition: all 200ms ease-out;
}
.right-sticky-section.expanded {
right: 280px;
}
.right-sticky-section .tool-icon {
float: right;
margin-right: 0;
}
/*
* Settings icons
*/
.tool-icon.gallery-icon {
background-image: url(../img/gallery.png);
background-position: 3px 3px;
background-size: 39px 39px;
}
.tool-icon.resize-icon {
background-image: url(../img/resize-icon.png);
background-position: 10px 10px;
background-size: 26px 26px;
}
.tool-icon.save-icon {
background-image: url(../img/save.png);
background-position: 6px 6px;
background-size: 36px 36px;
}
.tool-icon.gear-icon {
background-image: url(../img/gear.png);
background-position: 6px 7px;
background-size: 32px 32px;
}
.tool-icon.upload-cloud-icon {
background-image: url(../img/cloud_export.png);
background-position: 4px 0px;
background-size: 36px 36px;
position: relative;
}
.tool-icon.local-storage-icon {
background-image: url(../img/local-storage-icon.png);
background-position: 10px 12px;
background-size: 30px;
position: relative;
}
.tool-icon.import-icon {
background-image: url(../img/import-icon.png);
background-position: 10px 5px;
background-size: 26px;
position: relative;
}
.upload-cloud-icon .label {
position: absolute;
left: 0;
bottom: 4px;
right: 0;
font-size: 11px;
text-transform: uppercase;
color: #fff;
text-align: center;
}
.drawer-content {
overflow: hidden;
background-color: #444;
height: 550px;
max-height: 100%;
width: 280px;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
box-shadow: 0 0 5px 0 black;
}
.right-sticky-section.expanded .tool-icon {
padding-right: 1px;
}
.right-sticky-section .tool-icon.has-expanded-drawer {
position: relative;
background-color: #444;
margin-right: 0;
padding-right: 2px;
border-left : 3px solid gold;
}
.settings-section {
margin: 10px 20px;
font-size: 12px;
font-weight: bold;
color: #ccc;
text-shadow: 1px 1px #000;
}
.settings-section .button {
margin: 0;
}
.settings-title {
margin-top: 20px;
margin-bottom: 10px;
text-transform: uppercase;
border-bottom: 1px #aaa solid;
padding-bottom: 5px;
}
.settings-form-section {
margin-bottom: 10px;
}
.background-picker-wrapper {
overflow: hidden;
padding: 10px 5px 20px 5px;
}
.background-picker {
cursor: pointer;
float: left;
height: 35px;
width: 35px;
background-color: transparent;
margin-right: 15px;
padding: 1px;
position: relative;
}
.background-picker:after {
content: " ";
position: absolute;
top: -2px;
right: -2px;
bottom: -2px;
left: -2px;
}
.background-picker:hover:after {
border: #eee 1px solid;
}
.background-picker.selected:after {
border: gold 1px solid;
}
/* Gif/Png Export Setting panel*/
/*******************************/
.gif-upload-button,
.gif-render-button {
/*float : right;*/
margin-top : 10px;
margin-right : 10px;
}
.gif-export-radio-group {
margin:10px 0;
}
.gif-export-preview,
.png-export-preview {
margin-top:20px;
max-width:240px;
position:relative;
}
.png-export-preview {
margin:10px 0;
overflow: hidden;
}
.png-export-preview img {
float: left;
}
.png-upload-status {
margin : 10px 0;
}
.preview-upload-ongoing:before{
content: "Upload ongoing ...";
position: absolute;
display: block;
height: 100%;
width: 100%;
text-align: center;
padding-top: 45%;
box-sizing:border-box;
-moz-box-sizing:border-box;
background: rgba(0,0,0,0.5);
color: white;
}
/* Import panel */
.import-section,
.resize-section {
margin: 15px 0;
}
.import-section-title {
display : inline-block;
}
.import-section-title-small {
width: 35px;
}
.import-section-disabled {
color : #888;
}
.import-section-preview {
display : inline-block;
height : 60px;
width: 60px;
border : 1px dashed #999;
border-radius: 3px;
}
.import-size-field,
.resize-size-field {
width: 50px;
margin-right: 8px;
text-align: right;
}
.import-size-field:nth-of-type(2),
.resize-size-field:nth-of-type(2) {
margin-left: 5px;
}
.file-input-button {
margin-right: 8px;
border-radius: 2px;
}
.file-input-status {
display: inline-block;
width: 130px;
overflow: hidden;
height: 1.5rem;
word-break : break-all;
vertical-align: middle;
font-style: italic;
font-weight: normal;
text-shadow: none;
}
.save-field {
width: 100%;
}
#save-status {
margin-top: 10px;
}
.status {
height: 1.5rem;
vertical-align: middle;
font-weight: normal;
text-shadow: none;
}
[name=smooth-resize-checkbox] {
margin : 0 8px;
}
[name*=checkbox] {
vertical-align: middle;
}
.local-piskels-list {
width: 100%;
}
.local-piskel-item {
height: 3em;
}
.local-piskel-name {
width: 40%;
}
.local-piskel-save-date {
font-weight : normal;
}
.local-piskels-list a {
text-decoration: none;
}
.local-piskels-list a:hover {
text-decoration: underline;
}
.local-piskel-load-link {
color : gold;
}
.local-piskel-delete-link {
color : red;
}

View File

@ -1,118 +0,0 @@
/**
* Piskel specific CSS for spectrum widgets
*/
/* Widget's main container */
.sp-container {
border-radius: 4px;
background-color: #2B2B2B;
border: solid 4px #888;
padding: 5px 5px 0 5px;
box-shadow : 0 0 5px 0 black;
}
.sp-container[data-y-position=bottom] {
border-top-left-radius: 0;
}
.sp-container[data-y-position=top] {
border-bottom-left-radius: 0;
}
/* Color square container */
.sp-color, .sp-hue {
border : 1px solid #222;
}
/* Remove the padding on the input container */
.sp-replacer {
padding: 4px;
height: 100%;
border-width: 0;
box-sizing: border-box;
-moz-box-sizing:border-box;
background-color: #444;
}
.sp-replacer:hover {
background-color: #888;
}
/* Hide the triangle */
.sp-dd {
display: none;
}
/* */
.sp-preview {
margin-right: 0;
height: 100%;
width: 39px;
border-width: 0;
}
.sp-palette-row-selection {
max-width: 62px;
}
.sp-palette .sp-thumb-el {
margin : 0 5px 5px 0;
width: 24px;
height: 24px;
border-color: #444;
}
.sp-picker-container, .sp-palette-container {
padding-top: 5px;
padding-right: 5px;
padding-left: 5px;
border-left-width: 0;
border-right-width: 0;
}
.sp-picker-container {
padding: 5px;
padding-bottom: 300px;
margin-bottom: -295px;
}
.sp-slider {
height: 5px;
left: -2px;
right: -2px;
border: 2px solid white;
background: rgba(255,255,255,0);
opacity: 1;
border-radius: 2px;
box-shadow: 0 0 1px 1px rgba(0,0,0,0.5), inset 0 0 1px 1px rgba(0,0,0,0.5);
}
.sp-dragger {
border-radius: 8px;
height: 12px;
width: 12px;
border: 2px solid white;
background: none;
box-sizing:border-box;
-moz-box-sizing:border-box;
box-shadow: 0 0 1px 1px rgba(0,0,0,0.5), inset 0 0 1px 1px rgba(0,0,0,0.5);
}
.sp-palette .sp-thumb-el.sp-thumb-active {
border-color: gold;
box-shadow: 0 0 0px 1px gold;
}
.sp-input {
border: 1px solid #666;
margin: 0;
background: #111;
border-radius: 2px;
color: #D3D3D3;
font-family: Courier!important;
}
.sp-input.sp-validation-error {
background: #330000;
}

View File

@ -1,477 +0,0 @@
/***
Spectrum Colorpicker v1.1.2
https://github.com/bgrins/spectrum
Author: Brian Grinstead
License: MIT
***/
.sp-container {
position:absolute;
top:0;
left:0;
display:inline-block;
*display: inline;
*zoom: 1;
/* https://github.com/bgrins/spectrum/issues/40 */
z-index: 9999994;
overflow: hidden;
}
.sp-container.sp-flat {
position: relative;
}
/* http://ansciath.tumblr.com/post/7347495869/css-aspect-ratio */
.sp-top {
position:relative;
width: 100%;
display:inline-block;
}
.sp-top-inner {
position:absolute;
top:0;
left:0;
bottom:0;
right:0;
}
.sp-color {
position: absolute;
top:0;
left:0;
bottom:0;
right:20%;
}
.sp-hue {
position: absolute;
top:0;
right:0;
bottom:0;
left:84%;
height: 100%;
}
.sp-fill {
padding-top: 80%;
}
.sp-sat, .sp-val {
position: absolute;
top:0;
left:0;
right:0;
bottom:0;
}
.sp-alpha-enabled .sp-top {
margin-bottom: 18px;
}
.sp-alpha-enabled .sp-alpha {
display: block;
}
.sp-alpha-handle {
position:absolute;
top:-4px;
bottom: -4px;
width: 6px;
left: 50%;
cursor: pointer;
border: 1px solid black;
background: white;
opacity: .8;
}
.sp-alpha {
display: none;
position: absolute;
bottom: -14px;
right: 0;
left: 0;
height: 8px;
}
.sp-alpha-inner {
border: solid 1px #333;
}
/* Don't allow text selection */
.sp-container, .sp-replacer, .sp-preview, .sp-dragger, .sp-slider, .sp-alpha, .sp-alpha-handle, .sp-container.sp-dragging .sp-input, .sp-container button {
-webkit-user-select:none;
-moz-user-select: -moz-none;
-o-user-select:none;
user-select: none;
}
.sp-container.sp-input-disabled .sp-input-container {
display: none;
}
.sp-container.sp-buttons-disabled .sp-button-container {
display: none;
}
.sp-palette-only .sp-picker-container {
display: none;
}
.sp-palette-disabled .sp-palette-container {
display: none;
}
.sp-initial-disabled .sp-initial {
display: none;
}
/* Gradients for hue, saturation and value instead of images. Not pretty... but it works */
.sp-sat {
background-image: -webkit-gradient(linear, 0 0, 100% 0, from(#FFF), to(rgba(204, 154, 129, 0)));
background-image: -webkit-linear-gradient(left, #FFF, rgba(204, 154, 129, 0));
background-image: -moz-linear-gradient(left, #fff, rgba(204, 154, 129, 0));
background-image: -o-linear-gradient(left, #fff, rgba(204, 154, 129, 0));
background-image: -ms-linear-gradient(left, #fff, rgba(204, 154, 129, 0));
background-image: linear-gradient(to right, #fff, rgba(204, 154, 129, 0));
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr=#FFFFFFFF, endColorstr=#00CC9A81)";
filter : progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr='#FFFFFFFF', endColorstr='#00CC9A81');
}
.sp-val {
background-image: -webkit-gradient(linear, 0 100%, 0 0, from(#000000), to(rgba(204, 154, 129, 0)));
background-image: -webkit-linear-gradient(bottom, #000000, rgba(204, 154, 129, 0));
background-image: -moz-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));
background-image: -o-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));
background-image: -ms-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));
background-image: linear-gradient(to top, #000, rgba(204, 154, 129, 0));
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#00CC9A81, endColorstr=#FF000000)";
filter : progid:DXImageTransform.Microsoft.gradient(startColorstr='#00CC9A81', endColorstr='#FF000000');
}
.sp-hue {
background: -moz-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
background: -ms-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
background: -o-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
background: -webkit-gradient(linear, left top, left bottom, from(#ff0000), color-stop(0.17, #ffff00), color-stop(0.33, #00ff00), color-stop(0.5, #00ffff), color-stop(0.67, #0000ff), color-stop(0.83, #ff00ff), to(#ff0000));
background: -webkit-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
}
/* IE filters do not support multiple color stops.
Generate 6 divs, line them up, and do two color gradients for each.
Yes, really.
*/
.sp-1 {
height:17%;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0000', endColorstr='#ffff00');
}
.sp-2 {
height:16%;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff00', endColorstr='#00ff00');
}
.sp-3 {
height:17%;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ff00', endColorstr='#00ffff');
}
.sp-4 {
height:17%;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ffff', endColorstr='#0000ff');
}
.sp-5 {
height:16%;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0000ff', endColorstr='#ff00ff');
}
.sp-6 {
height:17%;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff00ff', endColorstr='#ff0000');
}
.sp-hidden {
display: none !important;
}
/* Clearfix hack */
.sp-cf:before, .sp-cf:after { content: ""; display: table; }
.sp-cf:after { clear: both; }
.sp-cf { *zoom: 1; }
/* Mobile devices, make hue slider bigger so it is easier to slide */
@media (max-device-width: 480px) {
.sp-color { right: 40%; }
.sp-hue { left: 63%; }
.sp-fill { padding-top: 60%; }
}
.sp-dragger {
border-radius: 5px;
height: 5px;
width: 5px;
border: 1px solid #fff;
background: #000;
cursor: pointer;
position:absolute;
top:0;
left: 0;
}
.sp-slider {
position: absolute;
top:0;
cursor:pointer;
height: 3px;
left: -1px;
right: -1px;
border: 1px solid #000;
background: white;
opacity: .8;
}
/*
Theme authors:
Here are the basic themeable display options (colors, fonts, global widths).
See http://bgrins.github.io/spectrum/themes/ for instructions.
*/
.sp-container {
border-radius: 0;
background-color: #ECECEC;
border: solid 1px #f0c49B;
padding: 0;
}
.sp-container, .sp-container button, .sp-container input, .sp-color, .sp-hue
{
font: normal 12px "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
}
.sp-top
{
margin-bottom: 3px;
}
.sp-color, .sp-hue
{
border: solid 1px #666;
}
/* Input */
.sp-input-container {
float:right;
width: 100px;
margin-bottom: 4px;
}
.sp-initial-disabled .sp-input-container {
width: 100%;
}
.sp-input {
font-size: 12px !important;
border: 1px inset;
padding: 4px 5px;
margin: 0;
width: 100%;
background:transparent;
border-radius: 3px;
color: #222;
}
.sp-input:focus {
border: 1px solid orange;
}
.sp-input.sp-validation-error
{
border: 1px solid red;
background: #fdd;
}
.sp-picker-container , .sp-palette-container
{
float:left;
position: relative;
padding: 10px;
padding-bottom: 300px;
margin-bottom: -290px;
}
.sp-picker-container
{
width: 172px;
border-left: solid 1px #fff;
}
/* Palettes */
.sp-palette-container
{
border-right: solid 1px #ccc;
}
.sp-palette .sp-thumb-el {
display: block;
position:relative;
float:left;
width: 24px;
height: 15px;
margin: 3px;
cursor: pointer;
border:solid 2px transparent;
}
.sp-palette .sp-thumb-el:hover, .sp-palette .sp-thumb-el.sp-thumb-active {
border-color: orange;
}
.sp-thumb-el
{
position:relative;
}
/* Initial */
.sp-initial
{
float: left;
border: solid 1px #333;
}
.sp-initial span {
width: 30px;
height: 25px;
border:none;
display:block;
float:left;
margin:0;
}
/* Buttons */
.sp-button-container {
float: right;
}
/* Replacer (the little preview div that shows up instead of the <input>) */
.sp-replacer {
margin:0;
overflow:hidden;
cursor:pointer;
padding: 4px;
display:inline-block;
*zoom: 1;
*display: inline;
border: solid 1px #91765d;
background: #eee;
color: #333;
vertical-align: middle;
}
.sp-replacer:hover, .sp-replacer.sp-active {
border-color: #F0C49B;
color: #111;
}
.sp-replacer.sp-disabled {
cursor:default;
border-color: silver;
color: silver;
}
.sp-dd {
padding: 2px 0;
height: 16px;
line-height: 16px;
float:left;
font-size:10px;
}
.sp-preview
{
position:relative;
width:25px;
height: 20px;
border: solid 1px #222;
margin-right: 5px;
float:left;
z-index: 0;
}
.sp-palette
{
*width: 220px;
max-width: 220px;
}
.sp-palette .sp-thumb-el
{
width:16px;
height: 16px;
margin:2px 1px;
border: solid 1px #d0d0d0;
}
.sp-container
{
padding-bottom:0;
}
/* Buttons: http://hellohappy.org/css3-buttons/ */
.sp-container button {
background-color: #eeeeee;
background-image: -webkit-linear-gradient(top, #eeeeee, #cccccc);
background-image: -moz-linear-gradient(top, #eeeeee, #cccccc);
background-image: -ms-linear-gradient(top, #eeeeee, #cccccc);
background-image: -o-linear-gradient(top, #eeeeee, #cccccc);
background-image: linear-gradient(to bottom, #eeeeee, #cccccc);
border: 1px solid #ccc;
border-bottom: 1px solid #bbb;
border-radius: 3px;
color: #333;
font-size: 14px;
line-height: 1;
padding: 5px 4px;
text-align: center;
text-shadow: 0 1px 0 #eee;
vertical-align: middle;
}
.sp-container button:hover {
background-color: #dddddd;
background-image: -webkit-linear-gradient(top, #dddddd, #bbbbbb);
background-image: -moz-linear-gradient(top, #dddddd, #bbbbbb);
background-image: -ms-linear-gradient(top, #dddddd, #bbbbbb);
background-image: -o-linear-gradient(top, #dddddd, #bbbbbb);
background-image: linear-gradient(to bottom, #dddddd, #bbbbbb);
border: 1px solid #bbb;
border-bottom: 1px solid #999;
cursor: pointer;
text-shadow: 0 1px 0 #ddd;
}
.sp-container button:active {
border: 1px solid #aaa;
border-bottom: 1px solid #888;
-webkit-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
-moz-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
-ms-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
-o-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
}
.sp-cancel
{
font-size: 11px;
color: #d93f3f !important;
margin:0;
padding:2px;
margin-right: 5px;
vertical-align: middle;
text-decoration:none;
}
.sp-cancel:hover
{
color: #d93f3f !important;
text-decoration: underline;
}
.sp-palette span:hover, .sp-palette span.sp-thumb-active
{
border-color: #000;
}
.sp-preview, .sp-alpha, .sp-thumb-el
{
position:relative;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);
}
.sp-preview-inner, .sp-alpha-inner, .sp-thumb-inner
{
display:block;
position:absolute;
top:0;left:0;bottom:0;right:0;
}
.sp-palette .sp-thumb-inner
{
background-position: 50% 50%;
background-repeat: no-repeat;
}
.sp-palette .sp-thumb-light.sp-thumb-active .sp-thumb-inner
{
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIVJREFUeNpiYBhsgJFMffxAXABlN5JruT4Q3wfi/0DsT64h8UD8HmpIPCWG/KemIfOJCUB+Aoacx6EGBZyHBqI+WsDCwuQ9mhxeg2A210Ntfo8klk9sOMijaURm7yc1UP2RNCMbKE9ODK1HM6iegYLkfx8pligC9lCD7KmRof0ZhjQACDAAceovrtpVBRkAAAAASUVORK5CYII=);
}
.sp-palette .sp-thumb-dark.sp-thumb-active .sp-thumb-inner
{
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAMdJREFUOE+tkgsNwzAMRMugEAahEAahEAZhEAqlEAZhEAohEAYh81X2dIm8fKpEspLGvudPOsUYpxE2BIJCroJmEW9qJ+MKaBFhEMNabSy9oIcIPwrB+afvAUFoK4H0tMaQ3XtlrggDhOVVMuT4E5MMG0FBbCEYzjYT7OxLEvIHQLY2zWwQ3D+9luyOQTfKDiFD3iUIfPk8VqrKjgAiSfGFPecrg6HN6m/iBcwiDAo7WiBeawa+Kwh7tZoSCGLMqwlSAzVDhoK+6vH4G0P5wdkAAAAASUVORK5CYII=);
}

View File

@ -1,247 +0,0 @@
body {
background: radial-gradient(circle, #000, #373737);
/* 16/06/2013 : -webkit still needed for
safari, safari mobile and android browser and chrome for android
cf http://caniuse.com/css-gradients */
background: -webkit-radial-gradient(circle, #000, #373737);
}
/* Browser fixes */
::-ms-clear {
display: none;
}
.allow-user-select {
-webkit-touch-callout: initial;
-webkit-user-select: initial;
-khtml-user-select: initial;
-moz-user-select: initial;
-ms-user-select: initial;
user-select: initial;
}
/**
* Application layout
*/
.main-wrapper {
position: absolute;
top: 5px;
right: 0;
bottom: 5px;
left: 0;
}
.column-wrapper {
text-align: center;
font-size: 0;
position: absolute;
left: 100px; /* Reserve room for tools on the left edge of the screen. */
top: 0;
right: 50px; /* Reserve room for actions on the right edge of the screen. */
bottom: 0;
}
.piskel-name-container {
overflow:hidden;
position:fixed;
top:10px;
left:10px;
color:white;
font-family:Tahoma;
z-index: 10000;
}
.piskel-name-container #piskel-name {
border :none;
color : lightgrey;
background: transparent;
font-size:16pt;
}
.column {
display: inline-block;
}
.left-column {
vertical-align: top;
height: 100%;
margin-right: 7px;
}
.main-column {
height: 100%;
position: relative;
}
.right-column {
vertical-align: top;
margin-left: 10px;
}
.drawing-canvas-container {
font-size: 0;
}
.sticky-section {
position: fixed;
top: 0;
bottom: 0;
z-index: 1000;
}
.sticky-section .sticky-section-wrap {
display: table;
height: 100%;
}
.sticky-section .vertical-centerer {
display: table-cell;
vertical-align: middle;
}
.left-sticky-section.sticky-section {
left: 0;
max-width: 100px;
}
.left-sticky-section .tool-icon {
float: left;
}
/**
* Canvases layout
*/
.canvas {
position: relative;
z-index: 1;
}
.canvas-container {
position: relative;
display: block;
}
.canvas-container .canvas-background {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.light-picker-background,
.light-canvas-background .canvas-background {
background: url(../img/canvas_background/light_canvas_background.png) repeat;
}
.medium-picker-background,
.medium-canvas-background .canvas-background {
background: url(../img/canvas_background/medium_canvas_background.png) repeat;
}
.lowcont-medium-picker-background,
.lowcont-medium-canvas-background .canvas-background {
background: url(../img/canvas_background/lowcont_medium_canvas_background.png) repeat;
}
.lowcont-dark-picker-background,
.lowcont-dark-canvas-background .canvas-background {
background: url(../img/canvas_background/lowcont_dark_canvas_background.png) repeat;
}
.layers-canvas {
opacity: 0.2;
}
.canvas.canvas-overlay,
.canvas.layers-canvas {
position: absolute;
top: 0;
left: 0;
}
/**
* Z-indexes should match the drawing area canvas superposition order :
* - 1 : draw layers below current layer
* - 2 : draw current layer
* - 3 : draw layers above current layer
* - 4 : draw the tools overlay
*/
.canvas.layers-below-canvas {z-index: 7;}
.canvas.drawing-canvas {z-index: 8;}
.canvas.layers-above-canvas {z-index: 9;}
.canvas.canvas-overlay {z-index: 10;}
/**
* Animated preview styles.
*/
.preview-container {
border : 0px Solid black;
border-radius:5px 0px 0px 5px;
box-shadow : 0px 0px 2px rgba(0,0,0,0.2);
font-size: 0;
}
.preview-container .canvas-container {
overflow : hidden;
}
.preview-container canvas {
border : 0px Solid transparent;
}
.display-fps {
float: left;
color: #aaa;
font-size: 12px;
min-width: 55px;
vertical-align: bottom;
line-height: 24px;
}
.range-fps {
overflow: hidden;
width: 120px;
}
/**
* User messages
*/
.user-message {
position: absolute;
right: 0;
bottom: 0;
background-color: #F9EDBE;
padding: 10px 47px;
border-top-left-radius: 7px;
color: #222;
border: #F0C36D 1px solid;
border-right: 0;
border-bottom: 0;
font-weight: bold;
font-size: 13px;
z-index: 10000;
max-width: 300px;
}
.user-message .close {
position: absolute;
top: 6px;
right: 17px;
color: gray;
font-weight: bold;
cursor: pointer;
font-size: 18px;
}
.user-message .close:hover {
color: black;
}
.image-link {
color : gold;
}

View File

@ -1,40 +0,0 @@
/**
* Layers container
*/
.layers-list-container {
}
.layers-title {
background-image: url('../../img/layers.svg');
background-size: 22px;
background-repeat: no-repeat;
background-position: 97%;
}
.layers-list {
font-size : 12px;
}
.layer-item {
height:24px;
line-height: 24px;
padding : 0 10px;
border-top: 1px solid #444;
cursor : pointer;
}
.layer-item:hover {
background : #222;
}
.current-layer-item,
.current-layer-item:hover {
background : #333;
color: gold;
}
.layers-button-arrow {
font-family : 'Lucida Grande', Calibri;
padding : 2px 6px 0 6px;
}

View File

@ -1,51 +0,0 @@
.palettes-list-container {
}
.palettes-title {
background-image: url('../img/layers.svg');
background-size: 22px;
background-repeat: no-repeat;
background-position: 97%;
}
.palettes-list-colors {
overflow:hidden;
}
.palettes-list-color {
cursor : pointer;
float: left;
margin : 0px 0 5px 5px;
width : 32px;
height : 32px;
position: relative;
}
.palettes-list-color div{
width : 32px;
height : 32px;
}
.palettes-list-color.primary:before,
.palettes-list-color.secondary:before {
content: "";
position: absolute;
bottom: -1px;
display: inline-block;
border: 7px solid gold;
border-top-color: transparent;
width: 0px;
height: 0px;
}
.palettes-list-color.primary:before {
left: -1px;
border-right-color: transparent;
}
.palettes-list-color.secondary:before {
right: -1px;
border-left-color: transparent;
}

View File

@ -1,34 +0,0 @@
.toolbox-container {
border: 4px solid #888;
font-size: medium;
color: white;
text-align: left;
border-radius: 4px;
margin-top: 10px;
}
.toolbox-title {
padding: 8px;
margin: 0;
font-size: 15px;
background: #222;
}
.toolbox-button-container {
overflow : hidden;
}
.toolbox-button {
margin: 0;
width: 25%;
float : left;
}
/* @override */
.button.toolbox-button {
border-left-width: 0;
}
.toolbox-button:last-child {
border-right-width: 0;
}

View File

@ -1,226 +0,0 @@
.tools-wrapper,
.options-wrapper,
.palette-wrapper {
float: left;
}
.tool-icon {
cursor : pointer;
width: 46px;
height: 46px;
margin: 1px;
background-color: #3a3a3a;
background-repeat: no-repeat;
background-position: 12px 12px;
background-size: 24px 24px;
}
.tool-icon.selected {
cursor: default;
background-color: #444;
border: 3px solid gold;
box-sizing: border-box;
-moz-box-sizing: border-box;
background-position: 9px 9px;
}
.tool-icon:hover {
background-color: #444;
}
/*
* Tool icons:
*/
.tool-icon.tool-pen {
background-image: url(../img/tools/pen.png);
}
.tool-icon.tool-vertical-mirror-pen {
background-image: url(../img/tools/mirror.png);
background-position: 0px 10px;
background-size: 38px 27px;
}
.tool-icon.tool-vertical-mirror-pen.selected {
background-position: -3px 7px;
}
.tool-icon.tool-paint-bucket {
background-image: url(../img/tools/paintbucket.png);
}
.tool-icon.tool-eraser {
background-image: url(../img/tools/eraser.png);
}
.tool-icon.tool-stroke {
background-image: url(../img/tools/stroke.png);
}
.tool-icon.tool-rectangle {
background-image: url(../img/tools/rectangle.png);
background-position: 12px 14px;
background-size: 24px 20px;
}
.tool-icon.tool-circle {
background-image: url(../img/tools/circle.png);
}
.tool-icon.tool-move {
background-image: url(../img/tools/hand.png);
background-size: 24px 24px;
}
.tool-icon.tool-rectangle-select {
background-image: url(../img/tools/rectangle_selection.png);
background-position: 12px 14px;
background-size: 24px 20px;
}
.tool-icon.tool-rectangle.selected,
.tool-icon.tool-rectangle-select.selected {
background-position: 9px 11px;
}
.tool-icon.tool-shape-select {
background-image: url(../img/tools/magicwand.png);
}
.tool-icon.tool-colorpicker {
background-image: url(../img/tools/eyedropper.png);
background-size: 23px 23px;
}
/*
* Tool cursors:
*/
.tool-paint-bucket .drawing-canvas-container:hover {
cursor: url(../img/icons/paint-bucket.png) 12 12, pointer;
}
.tool-vertical-mirror-pen .drawing-canvas-container:hover {
cursor: url(../img/icons/vertical-mirror-pen.png) 5 15, pointer;
}
.tool-pen .drawing-canvas-container:hover {
cursor: url(../img/icons/pen.png) 0 15, pointer;
}
.tool-eraser .drawing-canvas-container:hover {
cursor: url(../img/icons/eraser.png) 0 15, pointer;
}
.tool-stroke .drawing-canvas-container:hover {
cursor: url(../img/icons/pen.png) 0 15, pointer;
}
.tool-rectangle .drawing-canvas-container:hover {
cursor: url(../img/icons/rectangle.png) 0 15, pointer;
}
.tool-circle .drawing-canvas-container:hover {
cursor: url(../img/icons/circle.png) 2 15, pointer;
}
.tool-move .drawing-canvas-container:hover {
cursor: url(../img/icons/hand.png) 15 15, pointer;
}
.tool-rectangle-select .drawing-canvas-container:hover {
cursor: url(../img/icons/select.png) 15 15, pointer;
}
.tool-shape-select .drawing-canvas-container:hover {
cursor: url(../img/icons/wand.png) 15 15, pointer;
}
.tool-colorpicker .drawing-canvas-container:hover {
cursor: url(../img/icons/dropper.png) 0 15, pointer;
}
.swap-colors-icon {
background-image: url(../img/tools/swap-arrow-square-small-grey.png);
position: relative;
top: 50px;
left: 6px;
height: 18px;
width: 18px;
background-size: 18px;
opacity : 0.3;
cursor : pointer;
}
.swap-colors-icon:hover {
opacity : 1;
}
.tool-color-picker {
position:relative;
}
.tool-color-picker:nth-child(1) {
z-index : 100;
}
.tool-color-picker:nth-child(2) {
z-index : 90;
margin-top: 20px;
margin-left:-20px;
}
.tool-color-picker input {
width: 16px;
height: 16px;
text-indent: -10000px;
border: 1px solid black;
background: white;
cursor: pointer;
position : relative;
top: 10px;
margin-left: 2px;
}
.tool-color-picker .secondary-color-picker {
top : 18px;
margin-left: 0;
}
.palette-wrapper {
margin-top: 10px;
margin-left: 10px;
}
.palette-color[data-color=TRANSPARENT] {
position: relative;
top: 10px;
left: 10px;
background-color: white;
height : 16px;
width : 16px;
border: 2px solid #000;
background-size: 16px 16px;
background-position: 0 0;
background-image: -webkit-gradient(
linear,
left top,
right bottom,
color-stop(0, #fff),
color-stop(0.45, #fff),
color-stop(0.5, #ff0000),
color-stop(0.55, #fff),
color-stop(1, #fff)
);
background-image: -moz-linear-gradient(
left top,
#fff 0%,
#fff 45%,
#f00 50%,
#fff 55%,
#fff 100%
);
}

BIN
img/tools/lighten.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -41,6 +41,7 @@
<iframe src="templates/preview.html" onload="iframeloader.onLoad(event)" data-iframe-loader="display"></iframe>
<iframe src="templates/layers-list.html" onload="iframeloader.onLoad(event)" data-iframe-loader="display"></iframe>
<iframe src="templates/palettes-list.html" onload="iframeloader.onLoad(event)" data-iframe-loader="display"></iframe>
<div class="pull-bottom cursor-coordinates"></div>
</div>
</div>

View File

@ -1,62 +0,0 @@
// TODO(grosbouddha): put under pskl namespace.
var Constants = {
DEFAULT : {
HEIGHT : 32,
WIDTH : 32,
FPS : 12
},
MODEL_VERSION : 2,
MAX_HEIGHT : 1024,
MAX_WIDTH : 1024,
MINIMUM_ZOOM : 1,
PREVIEW_FILM_SIZE : 120,
ANIMATED_PREVIEW_WIDTH : 200,
DEFAULT_PEN_COLOR : '#000000',
TRANSPARENT_COLOR : 'rgba(0, 0, 0, 0)',
// Used for Spectrum input
PREFERRED_COLOR_FORMAT : 'rgb',
/*
* Fake semi-transparent color used to highlight transparent
* strokes and rectangles:
*/
SELECTION_TRANSPARENT_COLOR: 'rgba(255, 255, 255, 0.6)',
/*
* When a tool is hovering the drawing canvas, we highlight the eventual
* pixel target with this color:
*/
TOOL_TARGET_HIGHLIGHT_COLOR: 'rgba(255, 255, 255, 0.2)',
/*
* Default entry point for piskel web service:
*/
STATIC : {
URL : {
SAVE : 'http://3.piskel-app.appspot.com/store',
GET : 'http://3.piskel-app.appspot.com/get'
}
},
APPENGINE : {
URL : {
SAVE : 'save'
}
},
IMAGE_SERVICE_UPLOAD_URL : 'http://piskel-imgstore-a.appspot.com/__/upload',
IMAGE_SERVICE_GET_URL : 'http://piskel-imgstore-a.appspot.com/img/',
ZOOMED_OUT_BACKGROUND_COLOR : '#A0A0A0',
LEFT_BUTTON : 0,
MIDDLE_BUTTON : 1,
RIGHT_BUTTON : 2,
MOUSEMOVE_THROTTLING : 10,
ABSTRACT_FUNCTION : function () {throw 'abstract method should be implemented';}
};

View File

@ -1,51 +0,0 @@
// TODO(grosbouddha): put under pskl namespace.
var Events = {
TOOL_SELECTED : "TOOL_SELECTED",
TOOL_RELEASED : "TOOL_RELEASED",
SELECT_PRIMARY_COLOR: "SELECT_PRIMARY_COLOR",
SELECT_SECONDARY_COLOR: "SELECT_SECONDARY_COLOR",
PRIMARY_COLOR_SELECTED : 'PRIMARY_COLOR_SELECTED',
SECONDARY_COLOR_SELECTED : 'SECONDARY_COLOR_SELECTED',
DIALOG_DISPLAY : 'DIALOG_DISPLAY',
DIALOG_HIDE : 'DIALOG_HIDE',
PALETTE_LIST_UPDATED : 'PALETTE_LIST_UPDATED',
/**
* When this event is emitted, a request is sent to the localstorage
* Service to save the current framesheet. The storage service
* may not immediately store data (internal throttling of requests).
*/
LOCALSTORAGE_REQUEST: "LOCALSTORAGE_REQUEST",
/**
* Fired each time a user setting change.
* The payload will be:
* 1st argument: Name of the settings
* 2nd argument: New value
*/
USER_SETTINGS_CHANGED: "USER_SETTINGS_CHANGED",
CLOSE_SETTINGS_DRAWER : "CLOSE_SETTINGS_DRAWER",
/**
* The framesheet was reseted and is now probably drastically different.
* Number of frames, content of frames, color used for the palette may have changed.
*/
PISKEL_RESET: "PISKEL_RESET",
PISKEL_SAVED: "PISKEL_SAVED",
FRAME_SIZE_CHANGED : "FRAME_SIZE_CHANGED",
SELECTION_CREATED: "SELECTION_CREATED",
SELECTION_MOVE_REQUEST: "SELECTION_MOVE_REQUEST",
SELECTION_DISMISSED: "SELECTION_DISMISSED",
SHOW_NOTIFICATION: "SHOW_NOTIFICATION",
HIDE_NOTIFICATION: "HIDE_NOTIFICATION",
ZOOM_CHANGED : "ZOOM_CHANGED"
};

236
js/app.js
View File

@ -1,236 +0,0 @@
/**
* @require Constants
* @require Events
*/
(function () {
var ns = $.namespace("pskl");
/**
* Main application controller
*/
ns.app = {
init : function () {
/**
* True when piskel is running in static mode (no back end needed).
* When started from APP Engine, appEngineToken_ (Boolean) should be set on window.pskl
*/
this.isAppEngineVersion = !!pskl.appEngineToken_;
this.shortcutService = new pskl.service.keyboard.ShortcutService();
this.shortcutService.init();
var size = this.readSizeFromURL_();
var descriptor = new pskl.model.piskel.Descriptor('New Piskel', '');
var piskel = new pskl.model.Piskel(size.width, size.height, descriptor);
var layer = new pskl.model.Layer("Layer 1");
var frame = new pskl.model.Frame(size.width, size.height);
layer.addFrame(frame);
piskel.addLayer(layer);
this.piskelController = new pskl.controller.PiskelController(piskel);
this.piskelController.init();
this.paletteController = new pskl.controller.PaletteController();
this.paletteController.init();
this.palettesListController = new pskl.controller.PalettesListController();
this.palettesListController.init();
this.drawingController = new pskl.controller.DrawingController(this.piskelController, this.paletteController, $('#drawing-canvas-container'));
this.drawingController.init();
this.animationController = new pskl.controller.AnimatedPreviewController(this.piskelController, $('#preview-canvas-container'));
this.animationController.init();
this.minimapController = new pskl.controller.MinimapController(this.piskelController, this.animationController, this.drawingController, $('#preview-canvas-container'));
this.minimapController.init();
this.previewsController = new pskl.controller.PreviewFilmController(this.piskelController, $('#preview-list'));
this.previewsController.init();
this.layersListController = new pskl.controller.LayersListController(this.piskelController);
this.layersListController.init();
this.settingsController = new pskl.controller.settings.SettingsController(this.piskelController);
this.settingsController.init();
this.dialogsController = new pskl.controller.dialogs.DialogsController(this.piskelController);
this.dialogsController.init();
this.toolController = new pskl.controller.ToolController();
this.toolController.init();
this.selectionManager = new pskl.selection.SelectionManager(this.piskelController);
this.selectionManager.init();
this.historyService = new pskl.service.HistoryService(this.piskelController);
this.historyService.init();
this.notificationController = new pskl.controller.NotificationController();
this.notificationController.init();
this.localStorageService = new pskl.service.LocalStorageService(this.piskelController);
this.localStorageService.init();
this.imageUploadService = new pskl.service.ImageUploadService();
this.imageUploadService.init();
this.cheatsheetService = new pskl.service.keyboard.CheatsheetService();
this.cheatsheetService.init();
this.savedStatusService = new pskl.service.SavedStatusService(this.piskelController);
this.savedStatusService.init();
if (this.isAppEngineVersion) {
this.storageService = new pskl.service.AppEngineStorageService(this.piskelController);
} else {
this.storageService = new pskl.service.GithubStorageService(this.piskelController);
}
this.storageService.init();
var drawingLoop = new pskl.rendering.DrawingLoop();
drawingLoop.addCallback(this.render, this);
drawingLoop.start();
this.initTooltips_();
if (this.isAppEngineVersion) {
this.finishInitAppEngine_();
} else {
this.finishInitGithub_();
}
},
finishInitGithub_ : function () {
var framesheetId = this.readFramesheetIdFromURL_();
if (framesheetId) {
$.publish(Events.SHOW_NOTIFICATION, [{
"content" : "Loading animation with id : [" + framesheetId + "]"
}]);
this.loadFramesheetFromService(framesheetId);
}
},
finishInitAppEngine_ : function () {
if (pskl.appEnginePiskelData_ && pskl.appEnginePiskelData_.piskel) {
pskl.utils.serialization.Deserializer.deserialize(pskl.appEnginePiskelData_.piskel, function (piskel) {
piskel.setDescriptor(pskl.appEnginePiskelData_.descriptor);
pskl.app.piskelController.setPiskel(piskel);
pskl.app.animationController.setFPS(pskl.appEnginePiskelData_.fps);
});
}
},
isLoggedIn : function () {
return pskl.appEnginePiskelData_ && pskl.appEnginePiskelData_.isLoggedIn;
},
initTooltips_ : function () {
$('body').tooltip({
selector: '[rel=tooltip]'
});
},
render : function (delta) {
this.drawingController.render(delta);
this.animationController.render(delta);
this.previewsController.render(delta);
},
readSizeFromURL_ : function () {
var sizeParam = this.readUrlParameter_("size");
var size;
// parameter expected as size=64x48 => size=widthxheight
var parts = sizeParam.split("x");
if (parts && parts.length == 2 && !isNaN(parts[0]) && !isNaN(parts[1])) {
var width = parseInt(parts[0], 10),
height = parseInt(parts[1], 10);
size = {
height : Math.min(height, Constants.MAX_HEIGHT),
width : Math.min(width, Constants.MAX_WIDTH)
};
} else {
size = {
height : Constants.DEFAULT.HEIGHT,
width : Constants.DEFAULT.WIDTH
};
}
return size;
},
readFramesheetIdFromURL_ : function () {
return this.readUrlParameter_("frameId");
},
readUrlParameter_ : function (paramName) {
var searchString = window.location.search.substring(1);
var params = searchString.split("&");
for (var i = 0; i < params.length; i++) {
var param = params[i].split("=");
if (param[0] == paramName) {
return window.unescape(param[1]);
}
}
return "";
},
loadFramesheetFromService : function (frameId) {
var xhr = new XMLHttpRequest();
xhr.open('GET', Constants.STATIC.URL.GET + '?l=' + frameId, true);
xhr.responseType = 'text';
xhr.onload = function (e) {
var res = JSON.parse(this.responseText);
pskl.utils.serialization.Deserializer.deserialize(res.framesheet, function (piskel) {
pskl.app.piskelController.setPiskel(piskel);
pskl.app.animationController.setFPS(res.fps);
$.publish(Events.HIDE_NOTIFICATION);
});
};
xhr.onerror = function () {
$.publish(Events.HIDE_NOTIFICATION);
};
xhr.send();
},
store : function (callbacks) {
this.storageService.store(callbacks);
},
getFirstFrameAsPng : function () {
var firstFrame = this.piskelController.getFrameAt(0);
var canvasRenderer = new pskl.rendering.CanvasRenderer(firstFrame, 1);
canvasRenderer.drawTransparentAs('rgba(0,0,0,0)');
var firstFrameCanvas = canvasRenderer.render();
return firstFrameCanvas.toDataURL("image/png");
},
getFramesheetAsPng : function () {
var renderer = new pskl.rendering.PiskelRenderer(this.piskelController);
var framesheetCanvas = renderer.renderAsCanvas();
return framesheetCanvas.toDataURL("image/png");
},
uploadAsSpritesheetPNG : function () {
var imageData = this.getFramesheetAsPng();
this.imageUploadService.upload(imageData, this.openWindow.bind(this));
},
openWindow : function (url) {
var options = [
"dialog=yes", "scrollbars=no", "status=no",
"width=" + this.piskelController.getWidth() * this.piskelController.getFrameCount(),
"height=" + this.piskelController.getHeight()
].join(",");
window.open(url, "piskel-export", options);
}
};
})();

View File

@ -1,79 +0,0 @@
(function () {
var ns = $.namespace("pskl.controller");
ns.AnimatedPreviewController = function (piskelController, container) {
this.piskelController = piskelController;
this.container = container;
this.elapsedTime = 0;
this.currentIndex = 0;
this.setFPS(Constants.DEFAULT.FPS);
var zoom = this.calculateZoom_();
var frame = this.piskelController.getCurrentFrame();
var renderingOptions = {
"zoom": zoom,
"height" : frame.getHeight() * zoom,
"width" : frame.getWidth() * zoom
};
this.renderer = new pskl.rendering.frame.FrameRenderer(this.container, renderingOptions);
$.subscribe(Events.FRAME_SIZE_CHANGED, this.onFrameSizeChange_.bind(this));
};
ns.AnimatedPreviewController.prototype.init = function () {
// the oninput event won't work on IE10 unfortunately, but at least will provide a
// consistent behavior across all other browsers that support the input type range
// see https://bugzilla.mozilla.org/show_bug.cgi?id=853670
$("#preview-fps")[0].addEventListener('change', this.onFPSSliderChange.bind(this));
document.querySelector(".right-column").style.width = Constants.ANIMATED_PREVIEW_WIDTH + 'px';
};
ns.AnimatedPreviewController.prototype.onFPSSliderChange = function (evt) {
this.setFPS(parseInt($("#preview-fps")[0].value, 10));
};
ns.AnimatedPreviewController.prototype.setFPS = function (fps) {
this.fps = fps;
$("#preview-fps").val(this.fps);
$("#display-fps").html(this.fps + " FPS");
};
ns.AnimatedPreviewController.prototype.getFPS = function () {
return this.fps;
};
ns.AnimatedPreviewController.prototype.render = function (delta) {
this.elapsedTime += delta;
var index = Math.floor(this.elapsedTime / (1000/this.fps));
if (index != this.currentIndex) {
this.currentIndex = index;
if (!this.piskelController.hasFrameAt(this.currentIndex)) {
this.currentIndex = 0;
this.elapsedTime = 0;
}
this.renderer.render(this.piskelController.getFrameAt(this.currentIndex));
}
};
/**
* Calculate the preview zoom depending on the framesheet size
*/
ns.AnimatedPreviewController.prototype.calculateZoom_ = function () {
var frame = this.piskelController.getCurrentFrame();
var previewSize = 200,
hZoom = previewSize / frame.getHeight(),
wZoom = previewSize / frame.getWidth();
return Math.min(hZoom, wZoom);
};
ns.AnimatedPreviewController.prototype.onFrameSizeChange_ = function () {
var frame = this.piskelController.getCurrentFrame();
var zoom = this.calculateZoom_();
this.renderer.setDisplaySize(frame.getWidth() * zoom, frame.getHeight() * zoom);
this.renderer.setZoom(zoom);
this.renderer.setOffset(0, 0);
};
})();

View File

@ -1,335 +0,0 @@
(function () {
var ns = $.namespace("pskl.controller");
ns.DrawingController = function (piskelController, paletteController, container) {
/**
* @public
*/
this.piskelController = piskelController;
this.paletteController = paletteController;
/**
* @public
*/
this.overlayFrame = pskl.model.Frame.createEmptyFromFrame(piskelController.getCurrentFrame());
/**
* @private
*/
this.container = container;
// TODO(vincz): Store user prefs in a localstorage string ?
var renderingOptions = {
"zoom": this.calculateZoom_(),
"supportGridRendering" : true,
"height" : this.getContainerHeight_(),
"width" : this.getContainerWidth_(),
"xOffset" : 0,
"yOffset" : 0
};
this.overlayRenderer = new pskl.rendering.frame.CachedFrameRenderer(this.container, renderingOptions, ["canvas-overlay"]);
this.renderer = new pskl.rendering.frame.CachedFrameRenderer(this.container, renderingOptions, ["drawing-canvas"]);
this.layersRenderer = new pskl.rendering.layer.LayersRenderer(this.container, renderingOptions, piskelController);
this.compositeRenderer = new pskl.rendering.CompositeRenderer();
this.compositeRenderer
.add(this.overlayRenderer)
.add(this.renderer)
.add(this.layersRenderer);
// State of drawing controller:
this.isClicked = false;
this.previousMousemoveTime = 0;
this.currentToolBehavior = null;
};
ns.DrawingController.prototype.init = function () {
this.initMouseBehavior();
$.subscribe(Events.TOOL_SELECTED, $.proxy(function(evt, toolBehavior) {
this.currentToolBehavior = toolBehavior;
this.overlayFrame.clear();
}, this));
$(window).resize($.proxy(this.startResizeTimer_, this));
$.subscribe(Events.USER_SETTINGS_CHANGED, $.proxy(this.onUserSettingsChange_, this));
$.subscribe(Events.FRAME_SIZE_CHANGED, $.proxy(this.onFrameSizeChanged_, this));
this.centerColumnWrapperHorizontally_();
};
ns.DrawingController.prototype.initMouseBehavior = function() {
var body = $('body');
this.container.mousedown($.proxy(this.onMousedown_, this));
this.container.mouseenter($.proxy(this.onMouseenter_, this));
this.container.mouseleave($.proxy(this.onMouseleave_, this));
if (pskl.utils.UserAgent.isChrome) {
this.container.on('mousewheel', $.proxy(this.onMousewheel_, this));
} else {
this.container.on('wheel', $.proxy(this.onMousewheel_, this));
}
body.mouseup($.proxy(this.onMouseup_, this));
// Deactivate right click:
body.contextmenu(this.onCanvasContextMenu_);
};
ns.DrawingController.prototype.startResizeTimer_ = function () {
if (this.resizeTimer) {
window.clearInterval(this.resizeTimer);
}
this.resizeTimer = window.setTimeout($.proxy(this.afterWindowResize_, this), 200);
};
ns.DrawingController.prototype.afterWindowResize_ = function () {
var initialWidth = this.compositeRenderer.getDisplaySize().width;
this.compositeRenderer.setDisplaySize(this.getContainerWidth_(), this.getContainerHeight_());
this.centerColumnWrapperHorizontally_();
var ratio = this.compositeRenderer.getDisplaySize().width / initialWidth;
var newZoom = ratio * this.compositeRenderer.getZoom();
this.compositeRenderer.setZoom(newZoom);
$.publish(Events.ZOOM_CHANGED);
};
/**
* @private
*/
ns.DrawingController.prototype.onUserSettingsChange_ = function (evt, settingsName, settingsValue) {
if(settingsName == pskl.UserSettings.SHOW_GRID) {
console.warn('DrawingController:onUserSettingsChange_ not implemented !');
}
};
ns.DrawingController.prototype.onFrameSizeChanged_ = function () {
this.compositeRenderer.setDisplaySize(this.getContainerWidth_(), this.getContainerHeight_());
this.compositeRenderer.setZoom(this.calculateZoom_());
this.compositeRenderer.setOffset(0, 0);
$.publish(Events.ZOOM_CHANGED);
};
/**
* @private
*/
ns.DrawingController.prototype.onMouseenter_ = function (event) {
this.container.bind('mousemove', $.proxy(this.onMousemove_, this));
};
/**
* @private
*/
ns.DrawingController.prototype.onMouseleave_ = function (event) {
this.container.unbind('mousemove');
this.currentToolBehavior.hideHighlightedPixel(this.overlayFrame);
};
/**
* @private
*/
ns.DrawingController.prototype.onMousedown_ = function (event) {
var frame = this.piskelController.getCurrentFrame();
var coords = this.renderer.getCoordinates(event.clientX, event.clientY);
if (event.button === Constants.MIDDLE_BUTTON) {
if (frame.containsPixel(coords.x, coords.y)) {
$.publish(Events.SELECT_PRIMARY_COLOR, [frame.getPixel(coords.x, coords.y)]);
}
} else {
this.isClicked = true;
this.currentToolBehavior.hideHighlightedPixel(this.overlayFrame);
this.currentToolBehavior.applyToolAt(
coords.x,
coords.y,
this.getCurrentColor_(event),
frame,
this.overlayFrame,
event
);
$.publish(Events.LOCALSTORAGE_REQUEST);
}
};
/**
* @private
*/
ns.DrawingController.prototype.onMousemove_ = function (event) {
var currentTime = new Date().getTime();
// Throttling of the mousemove event:
if ((currentTime - this.previousMousemoveTime) > Constants.MOUSEMOVE_THROTTLING ) {
var coords = this.renderer.getCoordinates(event.clientX, event.clientY);
if (this.isClicked) {
this.currentToolBehavior.moveToolAt(
coords.x,
coords.y,
this.getCurrentColor_(event),
this.piskelController.getCurrentFrame(),
this.overlayFrame,
event
);
// TODO(vincz): Find a way to move that to the model instead of being at the interaction level.
// Eg when drawing, it may make sense to have it here. However for a non drawing tool,
// you don't need to draw anything when mousemoving and you request useless localStorage.
$.publish(Events.LOCALSTORAGE_REQUEST);
} else {
this.currentToolBehavior.moveUnactiveToolAt(
coords.x,
coords.y,
this.getCurrentColor_(event),
this.piskelController.getCurrentFrame(),
this.overlayFrame,
event
);
}
this.previousMousemoveTime = currentTime;
}
};
ns.DrawingController.prototype.onMousewheel_ = function (jQueryEvent) {
var event = jQueryEvent.originalEvent;
var delta = event.wheelDeltaY || (-2 * event.deltaY);
var currentZoom = this.renderer.getZoom();
var perfectZoom = this.calculateZoom_();
var step = perfectZoom / 10;
if (delta > 0) {
this.compositeRenderer.setZoom(currentZoom + step);
} else if (delta < 0) {
this.compositeRenderer.setZoom(currentZoom - step);
}
$.publish(Events.ZOOM_CHANGED);
};
/**
* @private
*/
ns.DrawingController.prototype.onMouseup_ = function (event) {
if(this.isClicked) {
// A mouse button was clicked on the drawing canvas before this mouseup event,
// the user was probably drawing on the canvas.
// Note: The mousemove movement (and the mouseup) may end up outside
// of the drawing canvas.
this.isClicked = false;
var coords = this.renderer.getCoordinates(event.clientX, event.clientY);
this.currentToolBehavior.releaseToolAt(
coords.x,
coords.y,
this.getCurrentColor_(event),
this.piskelController.getCurrentFrame(),
this.overlayFrame,
event
);
$.publish(Events.TOOL_RELEASED);
}
};
/**
* @private
*/
ns.DrawingController.prototype.getSpriteCoordinates = function(event) {
return this.renderer.getCoordinates(event.clientX, event.clientY);
};
/**
* @private
*/
ns.DrawingController.prototype.getCurrentColor_ = function (event) {
if(event.button == Constants.RIGHT_BUTTON) {
return this.paletteController.getSecondaryColor();
} else if(event.button == Constants.LEFT_BUTTON) {
return this.paletteController.getPrimaryColor();
} else {
return Constants.DEFAULT_PEN_COLOR;
}
};
/**
* @private
*/
ns.DrawingController.prototype.onCanvasContextMenu_ = function (event) {
if ($(event.target).closest('#drawing-canvas-container').length) {
// Deactivate right click on drawing canvas only.
event.preventDefault();
event.stopPropagation();
event.cancelBubble = true;
return false;
}
};
ns.DrawingController.prototype.render = function () {
var currentFrame = this.piskelController.getCurrentFrame();
if (!currentFrame.isSameSize(this.overlayFrame)) {
this.overlayFrame = pskl.model.Frame.createEmptyFromFrame(currentFrame);
}
this.layersRenderer.render();
this.renderer.render(currentFrame);
this.overlayRenderer.render(this.overlayFrame);
};
/**
* @private
*/
ns.DrawingController.prototype.calculateZoom_ = function() {
var frameHeight = this.piskelController.getCurrentFrame().getHeight(),
frameWidth = this.piskelController.getCurrentFrame().getWidth();
return Math.min(this.getAvailableWidth_()/frameWidth, this.getAvailableHeight_()/frameHeight);
};
ns.DrawingController.prototype.getAvailableHeight_ = function () {
return $('#main-wrapper').height();
};
ns.DrawingController.prototype.getAvailableWidth_ = function () {
var leftSectionWidth = $('.left-column').outerWidth(true),
rightSectionWidth = $('.right-column').outerWidth(true),
toolsContainerWidth = $('#tool-section').outerWidth(true),
settingsContainerWidth = $('#application-action-section').outerWidth(true),
availableWidth = $('#main-wrapper').width() - leftSectionWidth - rightSectionWidth - toolsContainerWidth - settingsContainerWidth;
return availableWidth-50;
};
ns.DrawingController.prototype.getContainerHeight_ = function () {
return this.calculateZoom_() * this.piskelController.getCurrentFrame().getHeight();
};
ns.DrawingController.prototype.getContainerWidth_ = function () {
return this.calculateZoom_() * this.piskelController.getCurrentFrame().getWidth();
};
/**
* @private
*/
ns.DrawingController.prototype.centerColumnWrapperHorizontally_ = function() {
var containerHeight = this.getContainerHeight_();
var verticalGapInPixel = Math.floor(($('#main-wrapper').height() - containerHeight) / 2);
$('#column-wrapper').css({
'top': verticalGapInPixel + 'px'
});
};
ns.DrawingController.prototype.getRenderer = function () {
return this.compositeRenderer;
};
ns.DrawingController.prototype.setOffset = function (x, y) {
this.compositeRenderer.setOffset(x, y);
$.publish(Events.ZOOM_CHANGED);
};
})();

View File

@ -1,59 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller');
ns.LayersListController = function (piskelController) {
this.piskelController = piskelController;
};
ns.LayersListController.prototype.init = function () {
this.layerItemTemplate_ = pskl.utils.Template.get('layer-item-template');
this.rootEl = document.querySelectorAll('.layers-list-container')[0];
this.layersListEl = document.querySelectorAll('.layers-list')[0];
this.rootEl.addEventListener('click', this.onClick_.bind(this));
$.subscribe(Events.PISKEL_RESET, this.renderLayerList_.bind(this));
this.renderLayerList_();
};
ns.LayersListController.prototype.renderLayerList_ = function () {
this.layersListEl.innerHTML = '';
var layers = this.piskelController.getLayers();
layers.forEach(this.addLayerItem.bind(this));
};
ns.LayersListController.prototype.addLayerItem = function (layer) {
var layerItemHtml = pskl.utils.Template.replace(this.layerItemTemplate_, {
layername : layer.getName()
});
var layerItem = pskl.utils.Template.createFromHTML(layerItemHtml);
if (this.piskelController.getCurrentLayer() === layer) {
layerItem.classList.add('current-layer-item');
}
this.layersListEl.insertBefore(layerItem, this.layersListEl.firstChild);
};
ns.LayersListController.prototype.onClick_ = function (evt) {
var el = evt.target || evt.srcElement;
if (el.nodeName == 'BUTTON') {
this.onButtonClick_(el);
} else if (el.nodeName == 'LI') {
var layerName = el.getAttribute('data-layer-name');
this.piskelController.selectLayerByName(layerName);
}
};
ns.LayersListController.prototype.onButtonClick_ = function (button) {
var action = button.getAttribute('data-action');
if (action == 'up') {
this.piskelController.moveLayerUp();
} else if (action == 'down') {
this.piskelController.moveLayerDown();
} else if (action == 'add') {
this.piskelController.createLayer();
} else if (action == 'delete') {
this.piskelController.removeCurrentLayer();
}
};
})();

View File

@ -1,90 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller');
ns.MinimapController = function (piskelController, animationController, drawingController, container) {
this.piskelController = piskelController;
this.animationController = animationController;
this.drawingController = drawingController;
this.container = container;
this.isClicked = false;
};
ns.MinimapController.prototype.init = function () {
// Create minimap DOM elements
this.cropFrame = document.createElement('DIV');
this.cropFrame.className = 'minimap-crop-frame';
this.cropFrame.style.display = 'none';
$(this.container).append(this.cropFrame);
// Init mouse events
$(this.container).mousedown(this.onMinimapMousedown_.bind(this));
$('body').mousemove(this.onMinimapMousemove_.bind(this));
$('body').mouseup(this.onMinimapMouseup_.bind(this));
$.subscribe(Events.ZOOM_CHANGED, $.proxy(this.renderMinimap_, this));
};
ns.MinimapController.prototype.renderMinimap_ = function () {
var zoomRatio = this.getDrawingAreaZoomRatio_();
if (zoomRatio > 1) {
this.displayCropFrame_(zoomRatio, this.drawingController.getRenderer().getOffset());
} else {
this.hideCropFrame_();
}
};
ns.MinimapController.prototype.displayCropFrame_ = function (ratio, offset) {
this.cropFrame.style.display = 'block';
this.cropFrame.style.top = (offset.y * this.animationController.renderer.getZoom()) + 'px';
this.cropFrame.style.left = (offset.x * this.animationController.renderer.getZoom()) + 'px';
var zoomRatio = this.getDrawingAreaZoomRatio_();
this.cropFrame.style.width = (this.container.width() / zoomRatio) + 'px';
this.cropFrame.style.height = (this.container.height() / zoomRatio) + 'px';
};
ns.MinimapController.prototype.hideCropFrame_ = function () {
this.cropFrame.style.display = 'none';
};
ns.MinimapController.prototype.onMinimapMousemove_ = function (evt) {
if (this.isClicked) {
if (this.getDrawingAreaZoomRatio_() > 1) {
var coords = this.getCoordinatesCenteredAround_(evt.clientX, evt.clientY);
this.drawingController.setOffset(coords.x, coords.y);
}
}
};
ns.MinimapController.prototype.onMinimapMousedown_ = function (evt) {
this.isClicked = true;
};
ns.MinimapController.prototype.onMinimapMouseup_ = function (evt) {
this.isClicked = false;
};
ns.MinimapController.prototype.getCoordinatesCenteredAround_ = function (x, y) {
var frameCoords = this.animationController.renderer.getCoordinates(x, y);
var zoomRatio = this.getDrawingAreaZoomRatio_();
var frameWidth = this.piskelController.getCurrentFrame().getWidth();
var frameHeight = this.piskelController.getCurrentFrame().getHeight();
var width = frameWidth / zoomRatio;
var height = frameHeight / zoomRatio;
return {
x : frameCoords.x - (width/2),
y : frameCoords.y - (height/2)
};
};
ns.MinimapController.prototype.getDrawingAreaZoomRatio_ = function () {
var drawingAreaZoom = this.drawingController.getRenderer().getZoom();
var drawingAreaFullHeight = this.piskelController.getCurrentFrame().getHeight() * drawingAreaZoom;
var zoomRatio = drawingAreaFullHeight / this.drawingController.getRenderer().getDisplaySize().height;
return zoomRatio;
};
})();

View File

@ -1,41 +0,0 @@
(function () {
var ns = $.namespace("pskl.controller");
ns.NotificationController = function () {};
/**
* @public
*/
ns.NotificationController.prototype.init = function() {
$.subscribe(Events.SHOW_NOTIFICATION, $.proxy(this.displayMessage_, this));
$.subscribe(Events.HIDE_NOTIFICATION, $.proxy(this.removeMessage_, this));
};
/**
* @private
*/
ns.NotificationController.prototype.displayMessage_ = function (evt, messageInfo) {
this.removeMessage_();
var message = document.createElement('div');
message.id = "user-message";
message.className = "user-message";
message.innerHTML = messageInfo.content;
message.innerHTML = message.innerHTML + "<div title='Close message' class='close'>x</div>";
document.body.appendChild(message);
$(message).find(".close").click($.proxy(this.removeMessage_, this));
if(messageInfo.behavior) {
messageInfo.behavior(message);
}
};
/**
* @private
*/
ns.NotificationController.prototype.removeMessage_ = function (evt) {
var message = $("#user-message");
if (message.length) {
message.remove();
}
};
})();

View File

@ -1,132 +0,0 @@
(function () {
var ns = $.namespace("pskl.controller");
ns.PaletteController = function () {
this.primaryColor = Constants.DEFAULT_PEN_COLOR;
this.secondaryColor = Constants.TRANSPARENT_COLOR;
};
/**
* @public
*/
ns.PaletteController.prototype.init = function() {
$.subscribe(Events.SELECT_PRIMARY_COLOR, this.onColorSelected_.bind(this, {isPrimary:true}));
$.subscribe(Events.SELECT_SECONDARY_COLOR, this.onColorSelected_.bind(this, {isPrimary:false}));
pskl.app.shortcutService.addShortcut('X', this.swapColors.bind(this));
pskl.app.shortcutService.addShortcut('D', this.resetColors.bind(this));
var spectrumCfg = {
showPalette: true,
showButtons: false,
showInput: true,
palette: [
['rgba(0,0,0,0)']
],
clickoutFiresChange : true,
beforeShow : function(tinycolor) {
tinycolor.setAlpha(1);
}
};
// Initialize colorpickers:
var colorPicker = $('#color-picker');
colorPicker.spectrum($.extend({color: Constants.DEFAULT_PEN_COLOR}, spectrumCfg));
colorPicker.change({isPrimary : true}, $.proxy(this.onPickerChange_, this));
this.setTitleOnPicker_(Constants.DEFAULT_PEN_COLOR, colorPicker);
var secondaryColorPicker = $('#secondary-color-picker');
secondaryColorPicker.spectrum($.extend({color: Constants.TRANSPARENT_COLOR}, spectrumCfg));
secondaryColorPicker.change({isPrimary : false}, $.proxy(this.onPickerChange_, this));
this.setTitleOnPicker_(Constants.TRANSPARENT_COLOR, secondaryColorPicker);
var swapColorsIcon = $('.swap-colors-icon');
swapColorsIcon.click(this.swapColors.bind(this));
};
/**
* @private
*/
ns.PaletteController.prototype.onPickerChange_ = function(evt, isPrimary) {
var inputPicker = $(evt.target);
if(evt.data.isPrimary) {
this.setPrimaryColor(inputPicker.val());
} else {
this.setSecondaryColor(inputPicker.val());
}
};
/**
* @private
*/
ns.PaletteController.prototype.onColorSelected_ = function(args, evt, color) {
var inputPicker = $(evt.target);
if(args.isPrimary) {
this.setPrimaryColor(color);
} else {
this.setSecondaryColor(color);
}
};
ns.PaletteController.prototype.setPrimaryColor = function (color) {
this.primaryColor = color;
this.updateColorPicker_(color, $('#color-picker'));
$.publish(Events.PRIMARY_COLOR_SELECTED, [color]);
};
ns.PaletteController.prototype.setSecondaryColor = function (color) {
this.secondaryColor = color;
this.updateColorPicker_(color, $('#secondary-color-picker'));
$.publish(Events.SECONDARY_COLOR_SELECTED, [color]);
};
ns.PaletteController.prototype.getPrimaryColor = function () {
return this.primaryColor;
};
ns.PaletteController.prototype.getSecondaryColor = function () {
return this.secondaryColor;
};
ns.PaletteController.prototype.swapColors = function () {
var primaryColor = this.getPrimaryColor();
this.setPrimaryColor(this.getSecondaryColor());
this.setSecondaryColor(primaryColor);
};
ns.PaletteController.prototype.resetColors = function () {
this.setPrimaryColor(Constants.DEFAULT_PEN_COLOR);
this.setSecondaryColor(Constants.TRANSPARENT_COLOR);
};
/**
* @private
*/
ns.PaletteController.prototype.updateColorPicker_ = function (color, colorPicker) {
if (color == Constants.TRANSPARENT_COLOR) {
// We can set the current palette color to transparent.
// You can then combine this transparent color with an advanced
// tool for customized deletions.
// Eg: bucket + transparent: Delete a colored area
// Stroke + transparent: hollow out the equivalent of a stroke
// The colorpicker can't be set to a transparent state.
// We set its background to white and insert the
// string "TRANSPARENT" to mimic this state:
colorPicker.spectrum("set", Constants.TRANSPARENT_COLOR);
colorPicker.val(Constants.TRANSPARENT_COLOR);
} else {
colorPicker.spectrum("set", color);
}
this.setTitleOnPicker_(color, colorPicker);
};
ns.PaletteController.prototype.setTitleOnPicker_ = function (title, colorPicker) {
var spectrumInputSelector = '.sp-replacer';
colorPicker.next(spectrumInputSelector).attr('title', title);
};
})();

View File

@ -1,130 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller');
var NO_PALETTE_ID = '__no-palette';
ns.PalettesListController = function () {
};
ns.PalettesListController.prototype.init = function () {
this.paletteColorTemplate_ = pskl.utils.Template.get('palette-color-template');
this.colorListContainer_ = document.querySelector('.palettes-list-colors');
this.colorPaletteSelect_ = document.querySelector('.palette-picker');
this.paletteListOptGroup_ = document.querySelector('.palette-picker-group');
this.colorPaletteSelect_.addEventListener('change', this.onPaletteSelected_.bind(this));
this.colorListContainer_.addEventListener('mouseup', this.onColorContainerMouseup.bind(this));
this.colorListContainer_.addEventListener('contextmenu', this.onColorContainerContextMenu.bind(this));
$.subscribe(Events.PALETTE_LIST_UPDATED, this.onPaletteListUpdated.bind(this));
$.subscribe(Events.PRIMARY_COLOR_SELECTED, this.onColorUpdated.bind(this, 'primary'));
$.subscribe(Events.SECONDARY_COLOR_SELECTED, this.onColorUpdated.bind(this, 'secondary'));
this.fillPaletteList();
this.fillColorListContainer();
};
ns.PalettesListController.prototype.fillPaletteList = function () {
var palettes = [{
id : NO_PALETTE_ID,
name : 'No palette'
}];
palettes = palettes.concat(this.retrievePalettes());
var html = palettes.map(function (palette) {
return pskl.utils.Template.replace('<option value="{{id}}">{{name}}</option>', palette);
}).join('');
this.paletteListOptGroup_.innerHTML = html;
};
ns.PalettesListController.prototype.fillColorListContainer = function () {
var html = '';
var palette = this.getSelectedPalette();
if (palette) {
html = palette.colors.map(function (color) {
return pskl.utils.Template.replace(this.paletteColorTemplate_, {color : color});
}.bind(this)).join('');
}
this.colorListContainer_.innerHTML = html;
};
ns.PalettesListController.prototype.getSelectedPalette = function (evt) {
var paletteId = this.colorPaletteSelect_.value;
var palettes = this.retrievePalettes();
var palette = this.getPaletteById(paletteId, palettes);
return palette;
};
ns.PalettesListController.prototype.onPaletteSelected_ = function (evt) {
var paletteId = this.colorPaletteSelect_.value;
if (paletteId === '__manage-palettes') {
console.log('DISPLAY DIALOG');
$.publish(Events.DIALOG_DISPLAY, 'manage-palettes');
this.colorPaletteSelect_.value = NO_PALETTE_ID;
}
this.fillColorListContainer();
};
ns.PalettesListController.prototype.onColorContainerContextMenu = function (event) {
event.preventDefault();
};
ns.PalettesListController.prototype.onColorContainerMouseup = function (event) {
var target = event.target;
var color = target.dataset.color;
if (color) {
if (event.button == Constants.LEFT_BUTTON) {
$.publish(Events.SELECT_PRIMARY_COLOR, [color]);
} else if (event.button == Constants.RIGHT_BUTTON) {
$.publish(Events.SELECT_SECONDARY_COLOR, [color]);
}
}
};
ns.PalettesListController.prototype.onColorUpdated = function (type, event, color) {
console.log('[PalettesListController] >>> ', arguments);
var colorContainer = this.colorListContainer_.querySelector('.palettes-list-color[data-color="'+color+'"]');
if (type === 'primary') {
this.removeClass_('primary', '.palettes-list-color');
colorContainer.classList.add('primary');
colorContainer.classList.remove('secondary');
} else if (type === 'secondary') {
this.removeClass_('secondary', '.palettes-list-color');
colorContainer.classList.add('secondary');
colorContainer.classList.remove('primary');
}
};
ns.PalettesListController.prototype.removeClass_ = function (cssClass, selector) {
var element = document.querySelector(selector + '.' + cssClass);
if (element) {
element.classList.remove(cssClass);
}
};
ns.PalettesListController.prototype.onPaletteListUpdated = function () {
this.fillPaletteList();
};
ns.PalettesListController.prototype.getPaletteById = function (paletteId, palettes) {
var match = null;
palettes.forEach(function (palette) {
if (palette.id === paletteId) {
match = palette;
}
});
return match;
};
ns.PalettesListController.prototype.retrievePalettes = function () {
var palettesString = window.localStorage.getItem('piskel.palettes');
return JSON.parse(palettesString) || [];
};
})();

View File

@ -1,227 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller');
ns.PiskelController = function (piskel) {
if (piskel) {
this.setPiskel(piskel);
} else {
throw 'A piskel instance is mandatory for instanciating PiskelController';
}
};
ns.PiskelController.prototype.setPiskel = function (piskel) {
this.piskel = piskel;
this.currentLayerIndex = 0;
this.currentFrameIndex = 0;
this.layerIdCounter = 1;
$.publish(Events.FRAME_SIZE_CHANGED);
$.publish(Events.PISKEL_RESET);
};
ns.PiskelController.prototype.init = function () {
pskl.app.shortcutService.addShortcut('up', this.selectPreviousFrame.bind(this));
pskl.app.shortcutService.addShortcut('down', this.selectNextFrame.bind(this));
pskl.app.shortcutService.addShortcut('n', this.addFrameAtCurrentIndex.bind(this));
pskl.app.shortcutService.addShortcut('shift+n', this.duplicateCurrentFrame.bind(this));
};
ns.PiskelController.prototype.getHeight = function () {
return this.piskel.getHeight();
};
ns.PiskelController.prototype.getWidth = function () {
return this.piskel.getWidth();
};
/**
* TODO : this should be removed
* FPS should be stored in the Piskel model and not in the
* animationController
* Then piskelController should be able to return this information
* @return {Number} Frames per second for the current animation
*/
ns.PiskelController.prototype.getFPS = function () {
return pskl.app.animationController.getFPS();
};
ns.PiskelController.prototype.getLayers = function () {
return this.piskel.getLayers();
};
ns.PiskelController.prototype.getCurrentLayer = function () {
return this.piskel.getLayerAt(this.currentLayerIndex);
};
ns.PiskelController.prototype.getCurrentFrame = function () {
var layer = this.getCurrentLayer();
return layer.getFrameAt(this.currentFrameIndex);
};
ns.PiskelController.prototype.getFrameAt = function (index) {
var frames = this.getLayers().map(function (l) {
return l.getFrameAt(index);
});
return pskl.utils.FrameUtils.merge(frames);
};
ns.PiskelController.prototype.hasFrameAt = function (index) {
return !!this.getCurrentLayer().getFrameAt(index);
};
ns.PiskelController.prototype.addFrame = function () {
this.addFrameAt(this.getFrameCount());
};
ns.PiskelController.prototype.addFrameAtCurrentIndex = function () {
this.addFrameAt(this.currentFrameIndex + 1);
};
ns.PiskelController.prototype.addFrameAt = function (index) {
var layers = this.getLayers();
layers.forEach(function (l) {
l.addFrameAt(this.createEmptyFrame_(), index);
}.bind(this));
$.publish(Events.PISKEL_RESET);
};
ns.PiskelController.prototype.createEmptyFrame_ = function () {
var w = this.piskel.getWidth(), h = this.piskel.getHeight();
return new pskl.model.Frame(w, h);
};
ns.PiskelController.prototype.removeFrameAt = function (index) {
var layers = this.getLayers();
layers.forEach(function (l) {
l.removeFrameAt(index);
});
// Current frame index is impacted if the removed frame was before the current frame
if (this.currentFrameIndex >= index && this.currentFrameIndex > 0) {
this.setCurrentFrameIndex(this.currentFrameIndex - 1);
}
$.publish(Events.PISKEL_RESET);
};
ns.PiskelController.prototype.duplicateCurrentFrame = function () {
this.duplicateFrameAt(this.currentFrameIndex);
};
ns.PiskelController.prototype.duplicateFrameAt = function (index) {
var layers = this.getLayers();
layers.forEach(function (l) {
l.duplicateFrameAt(index);
});
$.publish(Events.PISKEL_RESET);
};
ns.PiskelController.prototype.moveFrame = function (fromIndex, toIndex) {
var layers = this.getLayers();
layers.forEach(function (l) {
l.moveFrame(fromIndex, toIndex);
});
};
ns.PiskelController.prototype.getFrameCount = function () {
var layer = this.piskel.getLayerAt(0);
return layer.length();
};
ns.PiskelController.prototype.setCurrentFrameIndex = function (index) {
this.currentFrameIndex = index;
$.publish(Events.PISKEL_RESET);
};
ns.PiskelController.prototype.selectNextFrame = function () {
var nextIndex = this.currentFrameIndex + 1;
if (nextIndex < this.getFrameCount()) {
this.setCurrentFrameIndex(nextIndex);
}
};
ns.PiskelController.prototype.selectPreviousFrame = function () {
var nextIndex = this.currentFrameIndex - 1;
if (nextIndex >= 0) {
this.setCurrentFrameIndex(nextIndex);
}
};
ns.PiskelController.prototype.setCurrentLayerIndex = function (index) {
this.currentLayerIndex = index;
$.publish(Events.PISKEL_RESET);
};
ns.PiskelController.prototype.selectLayer = function (layer) {
var index = this.getLayers().indexOf(layer);
if (index != -1) {
this.setCurrentLayerIndex(index);
}
};
ns.PiskelController.prototype.selectLayerByName = function (name) {
if (this.hasLayerForName_(name)) {
var layer = this.piskel.getLayersByName(name)[0];
this.selectLayer(layer);
}
};
ns.PiskelController.prototype.generateLayerName_ = function () {
var name = "Layer " + this.layerIdCounter;
while (this.hasLayerForName_(name)) {
this.layerIdCounter++;
name = "Layer " + this.layerIdCounter;
}
return name;
};
ns.PiskelController.prototype.createLayer = function (name) {
if (!name) {
name = this.generateLayerName_();
}
if (!this.hasLayerForName_(name)) {
var layer = new pskl.model.Layer(name);
for (var i = 0 ; i < this.getFrameCount() ; i++) {
layer.addFrame(this.createEmptyFrame_());
}
this.piskel.addLayer(layer);
this.setCurrentLayerIndex(this.piskel.getLayers().length - 1);
} else {
throw 'Layer name should be unique';
}
};
ns.PiskelController.prototype.hasLayerForName_ = function (name) {
return this.piskel.getLayersByName(name).length > 0;
};
ns.PiskelController.prototype.moveLayerUp = function () {
var layer = this.getCurrentLayer();
this.piskel.moveLayerUp(layer);
this.selectLayer(layer);
};
ns.PiskelController.prototype.moveLayerDown = function () {
var layer = this.getCurrentLayer();
this.piskel.moveLayerDown(layer);
this.selectLayer(layer);
};
ns.PiskelController.prototype.removeCurrentLayer = function () {
if (this.getLayers().length > 1) {
var layer = this.getCurrentLayer();
this.piskel.removeLayer(layer);
this.setCurrentLayerIndex(0);
}
};
ns.PiskelController.prototype.serialize = function () {
return pskl.utils.Serializer.serializePiskel(this.piskel);
};
ns.PiskelController.prototype.load = function (data) {
this.deserialize(JSON.stringify(data));
};
})();

View File

@ -1,224 +0,0 @@
(function () {
var ns = $.namespace("pskl.controller");
ns.PreviewFilmController = function (piskelController, container) {
this.piskelController = piskelController;
this.container = container;
this.refreshZoom_();
this.redrawFlag = true;
};
ns.PreviewFilmController.prototype.init = function() {
$.subscribe(Events.TOOL_RELEASED, this.flagForRedraw_.bind(this));
$.subscribe(Events.PISKEL_RESET, this.flagForRedraw_.bind(this));
$.subscribe(Events.PISKEL_RESET, this.refreshZoom_.bind(this));
$('#preview-list-scroller').scroll(this.updateScrollerOverflows.bind(this));
this.updateScrollerOverflows();
};
ns.PreviewFilmController.prototype.addFrame = function () {
this.piskelController.addFrame();
this.piskelController.setCurrentFrameIndex(this.piskelController.getFrameCount() - 1);
this.updateScrollerOverflows();
};
ns.PreviewFilmController.prototype.flagForRedraw_ = function () {
this.redrawFlag = true;
};
ns.PreviewFilmController.prototype.refreshZoom_ = function () {
this.zoom = this.calculateZoom_();
};
ns.PreviewFilmController.prototype.render = function () {
if (this.redrawFlag) {
// TODO(vincz): Full redraw on any drawing modification, optimize.
this.createPreviews_();
this.redrawFlag = false;
}
};
ns.PreviewFilmController.prototype.updateScrollerOverflows = function () {
var scroller = $('#preview-list-scroller');
var scrollerHeight = scroller.height();
var scrollTop = scroller.scrollTop();
var scrollerContentHeight = $('#preview-list').height();
var treshold = $('.top-overflow').height();
var overflowTop = false,
overflowBottom = false;
if (scrollerHeight < scrollerContentHeight) {
if (scrollTop > treshold) {
overflowTop = true;
}
var scrollBottom = (scrollerContentHeight - scrollTop) - scrollerHeight;
if (scrollBottom > treshold) {
overflowBottom = true;
}
}
var wrapper = $('#preview-list-wrapper');
wrapper.toggleClass('top-overflow-visible', overflowTop);
wrapper.toggleClass('bottom-overflow-visible', overflowBottom);
};
ns.PreviewFilmController.prototype.createPreviews_ = function () {
this.container.html("");
// Manually remove tooltips since mouseout events were shortcut by the DOM refresh:
$(".tooltip").remove();
var frameCount = this.piskelController.getFrameCount();
for (var i = 0, l = frameCount; i < l ; i++) {
this.container.append(this.createPreviewTile_(i));
}
// Append 'new empty frame' button
var newFrameButton = document.createElement("div");
newFrameButton.id = "add-frame-action";
newFrameButton.className = "add-frame-action";
newFrameButton.innerHTML = "<p class='label'>Add new frame</p>";
this.container.append(newFrameButton);
$(newFrameButton).click(this.addFrame.bind(this));
var needDragndropBehavior = (frameCount > 1);
if(needDragndropBehavior) {
this.initDragndropBehavior_();
}
this.updateScrollerOverflows();
};
/**
* @private
*/
ns.PreviewFilmController.prototype.initDragndropBehavior_ = function () {
$("#preview-list").sortable({
placeholder: "preview-tile-drop-proxy",
update: $.proxy(this.onUpdate_, this),
items: ".preview-tile"
});
$("#preview-list").disableSelection();
};
/**
* @private
*/
ns.PreviewFilmController.prototype.onUpdate_ = function( event, ui ) {
var originFrameId = parseInt(ui.item.data("tile-number"), 10);
var targetInsertionId = $('.preview-tile').index(ui.item);
this.piskelController.moveFrame(originFrameId, targetInsertionId);
this.piskelController.setCurrentFrameIndex(targetInsertionId);
// TODO(grosbouddha): move localstorage request to the model layer?
$.publish(Events.LOCALSTORAGE_REQUEST);
};
/**
* @private
* TODO(vincz): clean this giant rendering function & remove listeners.
*/
ns.PreviewFilmController.prototype.createPreviewTile_ = function(tileNumber) {
var currentFrame = this.piskelController.getCurrentLayer().getFrameAt(tileNumber);
var previewTileRoot = document.createElement("li");
var classname = "preview-tile";
previewTileRoot.setAttribute("data-tile-number", tileNumber);
if (this.piskelController.getCurrentFrame() == currentFrame) {
classname += " selected";
}
previewTileRoot.className = classname;
var canvasContainer = document.createElement("div");
canvasContainer.className = "canvas-container";
var canvasBackground = document.createElement("div");
canvasBackground.className = "canvas-background";
canvasContainer.appendChild(canvasBackground);
previewTileRoot.addEventListener('click', this.onPreviewClick_.bind(this, tileNumber));
var cloneFrameButton = document.createElement("button");
cloneFrameButton.setAttribute('rel', 'tooltip');
cloneFrameButton.setAttribute('data-placement', 'right');
cloneFrameButton.setAttribute('title', 'Duplicate this frame');
cloneFrameButton.className = "tile-overlay duplicate-frame-action";
previewTileRoot.appendChild(cloneFrameButton);
cloneFrameButton.addEventListener('click', this.onAddButtonClick_.bind(this, tileNumber));
// TODO(vincz): Eventually optimize this part by not recreating a FrameRenderer. Note that the real optim
// is to make this update function (#createPreviewTile) less aggressive.
var renderingOptions = {
"zoom" : this.zoom,
"height" : this.piskelController.getCurrentFrame().getHeight() * this.zoom,
"width" : this.piskelController.getCurrentFrame().getWidth() * this.zoom
};
var currentFrameRenderer = new pskl.rendering.frame.FrameRenderer($(canvasContainer), renderingOptions, ["tile-view"]);
currentFrameRenderer.render(currentFrame);
previewTileRoot.appendChild(canvasContainer);
if(tileNumber > 0 || this.piskelController.getFrameCount() > 1) {
// Add 'remove frame' button.
var deleteButton = document.createElement("button");
deleteButton.setAttribute('rel', 'tooltip');
deleteButton.setAttribute('data-placement', 'right');
deleteButton.setAttribute('title', 'Delete this frame');
deleteButton.className = "tile-overlay delete-frame-action";
deleteButton.addEventListener('click', this.onDeleteButtonClick_.bind(this, tileNumber));
previewTileRoot.appendChild(deleteButton);
// Add 'dragndrop handle'.
var dndHandle = document.createElement("div");
dndHandle.className = "tile-overlay dnd-action";
previewTileRoot.appendChild(dndHandle);
}
var tileCount = document.createElement("div");
tileCount.className = "tile-overlay tile-count";
tileCount.innerHTML = tileNumber + 1;
previewTileRoot.appendChild(tileCount);
return previewTileRoot;
};
ns.PreviewFilmController.prototype.onPreviewClick_ = function (index, evt) {
// has not class tile-action:
if(!evt.target.classList.contains('tile-overlay')) {
this.piskelController.setCurrentFrameIndex(index);
}
};
ns.PreviewFilmController.prototype.onDeleteButtonClick_ = function (index, evt) {
this.piskelController.removeFrameAt(index);
$.publish(Events.LOCALSTORAGE_REQUEST); // Should come from model
this.updateScrollerOverflows();
};
ns.PreviewFilmController.prototype.onAddButtonClick_ = function (index, evt) {
this.piskelController.duplicateFrameAt(index);
$.publish(Events.LOCALSTORAGE_REQUEST); // Should come from model
this.piskelController.setCurrentFrameIndex(index + 1);
this.updateScrollerOverflows();
};
/**
* Calculate the preview zoom depending on the piskel size
*/
ns.PreviewFilmController.prototype.calculateZoom_ = function () {
var curFrame = this.piskelController.getCurrentFrame(),
frameHeight = curFrame.getHeight(),
frameWidth = curFrame.getWidth(),
maxFrameDim = Math.max(frameWidth, frameHeight);
var previewHeight = Constants.PREVIEW_FILM_SIZE * frameHeight / maxFrameDim;
var previewWidth = Constants.PREVIEW_FILM_SIZE * frameWidth / maxFrameDim;
return pskl.PixelUtils.calculateZoom(previewHeight, previewWidth, frameHeight, frameWidth) || 1;
};
})();

View File

@ -1,145 +0,0 @@
(function () {
var ns = $.namespace("pskl.controller");
ns.ToolController = function () {
var toDescriptor = function (id, shortcut, instance) {
return {id:id, shortcut:shortcut, instance:instance};
};
this.tools = [
toDescriptor('simplePen', 'P', new pskl.drawingtools.SimplePen()),
toDescriptor('verticalMirrorPen', 'V', new pskl.drawingtools.VerticalMirrorPen()),
toDescriptor('eraser', 'E', new pskl.drawingtools.Eraser()),
toDescriptor('paintBucket', 'B', new pskl.drawingtools.PaintBucket()),
toDescriptor('stroke', 'L', new pskl.drawingtools.Stroke()),
toDescriptor('rectangle', 'R', new pskl.drawingtools.Rectangle()),
toDescriptor('circle', 'C', new pskl.drawingtools.Circle()),
toDescriptor('move', 'M', new pskl.drawingtools.Move()),
toDescriptor('rectangleSelect', 'S', new pskl.drawingtools.RectangleSelect()),
toDescriptor('shapeSelect', 'Z', new pskl.drawingtools.ShapeSelect()),
toDescriptor('colorPicker', 'O', new pskl.drawingtools.ColorPicker())
];
this.currentSelectedTool = this.tools[0];
this.previousSelectedTool = this.tools[0];
};
/**
* @public
*/
ns.ToolController.prototype.init = function() {
this.createToolsDom_();
this.addKeyboardShortcuts_();
// Initialize tool:
// Set SimplePen as default selected tool:
this.selectTool_(this.tools[0]);
// Activate listener on tool panel:
$("#tool-section").mousedown($.proxy(this.onToolIconClicked_, this));
};
/**
* @private
*/
ns.ToolController.prototype.activateToolOnStage_ = function(tool) {
var stage = $("body");
var previousSelectedToolClass = stage.data("selected-tool-class");
if(previousSelectedToolClass) {
stage.removeClass(previousSelectedToolClass);
stage.removeClass(pskl.drawingtools.Move.TOOL_ID);
}
stage.addClass(tool.instance.toolId);
stage.data("selected-tool-class", tool.instance.toolId);
};
/**
* @private
*/
ns.ToolController.prototype.selectTool_ = function(tool) {
this.currentSelectedTool = tool;
this.activateToolOnStage_(this.currentSelectedTool);
var selectedToolElement = $('#tool-section .tool-icon.selected');
var toolElement = $('[data-tool-id=' + tool.instance.toolId + ']');
selectedToolElement.removeClass('selected');
toolElement.addClass('selected');
$.publish(Events.TOOL_SELECTED, [tool.instance]);
};
/**
* @private
*/
ns.ToolController.prototype.onToolIconClicked_ = function(evt) {
var target = $(evt.target);
var clickedTool = target.closest(".tool-icon");
if(clickedTool.length) {
var toolId = clickedTool.data().toolId;
var tool = this.getToolById_(toolId);
if (tool) {
this.selectTool_(tool);
}
}
};
ns.ToolController.prototype.onKeyboardShortcut_ = function(charkey) {
for (var i = 0 ; i < this.tools.length ; i++) {
var tool = this.tools[i];
if (tool.shortcut.toLowerCase() === charkey.toLowerCase()) {
this.selectTool_(tool);
}
}
};
ns.ToolController.prototype.getToolById_ = function (toolId) {
for(var i = 0 ; i < this.tools.length ; i++) {
var tool = this.tools[i];
if (tool.instance.toolId == toolId) {
return tool;
}
}
return null;
};
/**
* @private
*/
ns.ToolController.prototype.createToolsDom_ = function() {
var toolMarkup = '';
for(var i = 0 ; i < this.tools.length ; i++) {
toolMarkup += this.getToolMarkup_(this.tools[i]);
}
$('#tools-container').html(toolMarkup);
};
/**
* @private
*/
ns.ToolController.prototype.getToolMarkup_ = function(tool) {
var toolId = tool.instance.toolId;
var classList = ['tool-icon', toolId];
if (this.currentSelectedTool == tool) {
classList.push('selected');
}
var tpl = pskl.utils.Template.get('drawing-tool-item-template');
return pskl.utils.Template.replace(tpl, {
cssclass : classList.join(' '),
toolid : toolId,
title : this.getTooltipText_(tool)
});
};
ns.ToolController.prototype.getTooltipText_ = function (tool) {
return tool.instance.helpText + ' (' + tool.shortcut + ')';
};
ns.ToolController.prototype.addKeyboardShortcuts_ = function () {
for(var i = 0 ; i < this.tools.length ; i++) {
pskl.app.shortcutService.addShortcut(this.tools[i].shortcut, this.onKeyboardShortcut_.bind(this));
}
};
})();

View File

@ -1,62 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller.dialogs');
var dialogs = {
'manage-palettes' : {
template : 'templates/dialogs/manage-palettes.html',
controller : ns.PaletteManagerController
}
};
ns.DialogsController = function (piskelController) {
this.piskelController = piskelController;
this.currentDialog_ = null;
};
ns.DialogsController.prototype.init = function () {
this.dialogContainer_ = document.getElementById('dialog-container');
this.dialogWrapper_ = document.getElementById('dialog-container-wrapper');
$.subscribe(Events.DIALOG_DISPLAY, this.onDialogDisplayEvent_.bind(this));
$.subscribe(Events.DIALOG_HIDE, this.onDialogHideEvent_.bind(this));
pskl.app.shortcutService.addShortcut('alt+P', this.onDialogDisplayEvent_.bind(this, null, 'manage-palettes'));
};
ns.DialogsController.prototype.onDialogDisplayEvent_ = function (evt, dialogId) {
if (!this.isDisplayed()) {
var config = dialogs[dialogId];
if (config) {
this.dialogContainer_.innerHTML = pskl.utils.Template.get(config.template);
(new config.controller(this.piskelController)).init();
this.showDialogWrapper_();
this.currentDialog_ = dialogId;
} else {
console.error('Could not find dialog configuration for dialogId : ' + dialogId);
}
}
};
ns.DialogsController.prototype.onDialogHideEvent_ = function () {
this.hideDialog();
};
ns.DialogsController.prototype.showDialogWrapper_ = function () {
pskl.app.shortcutService.addShortcut('ESC', this.hideDialog.bind(this));
this.dialogWrapper_.style.display = 'block';
};
ns.DialogsController.prototype.hideDialog = function () {
this.hideDialogWrapper_();
this.currentDialog_ = null;
};
ns.DialogsController.prototype.hideDialogWrapper_ = function () {
pskl.app.shortcutService.removeShortcut('ESC');
this.dialogWrapper_.style.display = 'none';
};
ns.DialogsController.prototype.isDisplayed = function () {
return this.currentDialog_ !== null;
};
})();

View File

@ -1,359 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller.dialogs');
var tinycolor = window.tinycolor;
var SELECTED_CLASSNAME = 'selected';
var NEW_COLOR_CLASS = 'palette-manager-new-color';
var CLOSE_ICON_CLASS = 'palette-manager-delete-card';
var EDIT_NAME_CLASS = 'palette-manager-details-head-edit-icon';
ns.PaletteManagerController = function (piskelController) {
this.piskelController = piskelController;
this.palettes = this.retrieveUserPalettes();
this.originalPalettes = this.retrieveUserPalettes();
this.selectedPaletteId = null;
};
ns.PaletteManagerController.prototype.init = function () {
this.palettesList = document.querySelector('.palette-manager-list');
this.paletteBody = document.querySelector('.palette-manager-details-body');
this.paletteHead = document.querySelector('.palette-manager-details-head');
this.createButton = document.querySelector('.palette-manager-actions-button[data-action="create"]');
this.saveAllButton = document.querySelector('.palette-manager-actions-button[data-action="save-all"]');
this.closeButton = document.querySelector('.palette-manager-close');
this.colorCardTemplate = pskl.utils.Template.get('palette-color-card-template');
this.newColorTemplate = pskl.utils.Template.get('palette-new-color-template');
this.paletteHeadTemplate = pskl.utils.Template.get('palette-details-head-template');
// Events
this.palettesList.addEventListener('click', this.onPaletteListClick.bind(this));
// Delegated event listener for events repeated on all cards
this.paletteBody.addEventListener('click', this.delegatedPaletteBodyClick.bind(this));
this.paletteHead.addEventListener('click', this.delegatedPaletteHeadClick.bind(this));
this.createButton.addEventListener('click', this.createPalette.bind(this));
this.saveAllButton.addEventListener('click', this.saveAll.bind(this));
this.closeButton.addEventListener('click', this.closeDialog.bind(this));
// Init markup
this.createPaletteListMarkup();
if (this.palettes.length > 0) {
this.selectPalette(this.palettes[0].id);
} else {
console.error('[PaletteManagerController] >>> Implement fallback screen when no palette can be retrieved');
}
};
ns.PaletteManagerController.prototype.closeDialog = function () {
$.publish(Events.DIALOG_HIDE);
};
ns.PaletteManagerController.prototype.createPalette = function () {
var name = window.prompt('Please enter a name for your palette', 'New palette');
if (name) {
var palette = this.createPaletteObject(name);
this.palettes.push(palette);
this.createPaletteListMarkup();
this.selectPalette(palette.id);
}
};
ns.PaletteManagerController.prototype.createPaletteObject = function (name) {
return {
id : 'palette-' + Date.now() + '-' + Math.floor(Math.random()*1000),
name : name,
colors : []
};
};
ns.PaletteManagerController.prototype.selectPalette = function (paletteId) {
this.deselectCurrentPalette();
var paletteListItem = this.palettesList.querySelector('[data-palette-id='+paletteId+']');
if (paletteListItem) {
this.selectedPaletteId = paletteId;
paletteListItem.classList.add(SELECTED_CLASSNAME);
this.refreshPaletteDetails();
}
};
ns.PaletteManagerController.prototype.refreshPaletteDetails = function () {
this.createPaletteHeadMarkup();
this.createPaletteBodyMarkup();
this.initPaletteDetailsEvents();
this.initPaletteCardsSpectrum();
};
ns.PaletteManagerController.prototype.createPaletteListMarkup = function () {
var html = this.palettes.map(function (palette) {
var paletteCopy = {
id : palette.id,
name : this.isPaletteModified(palette) ? palette.name + " *" : palette.name
};
return pskl.utils.Template.replace('<li data-palette-id="{{id}}">{{name}}</li>', paletteCopy);
}.bind(this)).join('');
this.palettesList.innerHTML = html;
};
/**
* Fill the palette body container with color cards for the selected palette
*/
ns.PaletteManagerController.prototype.createPaletteHeadMarkup = function () {
var palette = this.getSelectedPalette();
var dict = {
'name' : palette.name,
'save:disabled' : !this.isPaletteModified(palette),
'revert:disabled' : !this.isPaletteModified(palette),
'delete:disabled' : this.palettes.length < 2
};
var html = pskl.utils.Template.replace(this.paletteHeadTemplate, dict);
this.paletteHead.innerHTML = html;
};
ns.PaletteManagerController.prototype.isPaletteModified = function (palette) {
var isModified = false;
var originalPalette = this.getPaletteById(palette.id, this.originalPalettes);
if (originalPalette) {
var differentName = originalPalette.name !== palette.name;
var differentColors = palette.colors.join('') !== originalPalette.colors.join('');
isModified = differentName || differentColors;
} else {
isModified = true;
}
return isModified;
};
/**
* Fill the palette body container with color cards for the selected palette
*/
ns.PaletteManagerController.prototype.createPaletteBodyMarkup = function () {
var palette = this.getSelectedPalette();
var html = this.getColorCardsMarkup(palette.colors);
html += pskl.utils.Template.replace(this.newColorTemplate, {classname : NEW_COLOR_CLASS});
this.paletteBody.innerHTML = html;
};
ns.PaletteManagerController.prototype.initPaletteDetailsEvents = function () {
// New Card click event
var newCard = this.paletteBody.querySelector('.' + NEW_COLOR_CLASS);
newCard.addEventListener('click', this.onNewCardClick.bind(this));
if (this.palettes.length < 2) {
var deleteButton = this.paletteHead.querySelector('.palette-manager-palette-button[data-action="delete"]');
deleteButton.setAttribute("disabled", "disabled");
}
};
ns.PaletteManagerController.prototype.onNewCardClick = function () {
var color;
var palette = this.getSelectedPalette();
if (palette && palette.colors.length > 0) {
color = palette.colors[palette.colors.length-1];
} else {
color = '#FFFFFF';
}
this.addColorInSelectedPalette(color);
};
ns.PaletteManagerController.prototype.delegatedPaletteBodyClick = function (event) {
var target = event.target;
if (target.classList.contains(CLOSE_ICON_CLASS)) {
var colorId = parseInt(target.parentNode.dataset.colorId, 10);
this.removeColorInSelectedPalette(colorId);
}
};
ns.PaletteManagerController.prototype.delegatedPaletteHeadClick = function (event) {
var target = event.target;
if (target.classList.contains(EDIT_NAME_CLASS)) {
this.renameSelectedPalette();
} else if (target.classList.contains('palette-manager-palette-button')) {
var action = target.dataset.action;
if (action === 'save') {
this.savePalette(this.getSelectedPalette().id);
} else if (action === 'revert') {
this.revertChanges();
} else if (action === 'delete') {
this.deleteSelectedPalette();
}
}
};
ns.PaletteManagerController.prototype.initPaletteCardsSpectrum = function () {
var oSelf = this;
var colorSquares = $(':not(.' + NEW_COLOR_CLASS + ')>.palette-manager-color-square');
colorSquares.spectrum({
clickoutFiresChange : true,
showInput: true,
showButtons: false,
change : function (color) {
var target = this;
var colorId = parseInt(target.parentNode.dataset.colorId, 10);
oSelf.updateColorInSelectedPalette(colorId, color);
},
beforeShow : function() {
var target = this;
var colorId = parseInt(target.parentNode.dataset.colorId, 10);
var palette = oSelf.getSelectedPalette();
var color = palette.colors[colorId];
colorSquares.spectrum("set", color);
}
});
};
ns.PaletteManagerController.prototype.updateColorInSelectedPalette = function (colorId, color) {
var palette = this.getSelectedPalette();
palette.colors.splice(colorId, 1, '#' + (color.toHex().toUpperCase()));
this.createPaletteListMarkup();
this.selectPalette(this.selectedPaletteId);
};
ns.PaletteManagerController.prototype.addColorInSelectedPalette = function (color) {
var selectedPalette = this.getSelectedPalette();
selectedPalette.colors.push(color);
this.createPaletteListMarkup();
this.selectPalette(this.selectedPaletteId);
};
ns.PaletteManagerController.prototype.removeColorInSelectedPalette = function (colorId) {
var palette = this.getSelectedPalette();
palette.colors.splice(colorId, 1);
this.createPaletteListMarkup();
this.selectPalette(this.selectedPaletteId);
};
ns.PaletteManagerController.prototype.renameSelectedPalette = function () {
var palette = this.getSelectedPalette();
var name = window.prompt('Please enter a new name for palette "' + palette.name + '"', palette.name);
if (name) {
palette.name = name;
this.createPaletteListMarkup();
this.selectPalette(palette.id);
}
};
ns.PaletteManagerController.prototype.getSelectedPalette = function () {
return this.getPaletteById(this.selectedPaletteId, this.palettes);
};
ns.PaletteManagerController.prototype.getColorCardsMarkup = function (colors) {
var html = colors.map(function (color, index) {
var dict = {
colorId : index,
hex : color,
rgb : tinycolor(color).toRgbString(),
hsl : tinycolor(color).toHslString()
};
return pskl.utils.Template.replace(this.colorCardTemplate, dict);
}.bind(this)).join('');
return html;
};
ns.PaletteManagerController.prototype.getPaletteById = function (paletteId, palettes) {
var match = null;
palettes.forEach(function (palette) {
if (palette.id === paletteId) {
match = palette;
}
});
return match;
};
ns.PaletteManagerController.prototype.removePaletteById = function (paletteId, palettes) {
var palette = this.getPaletteById(paletteId, palettes);
if (palette) {
var index = palettes.indexOf(palette);
palettes.splice(index, 1);
}
};
ns.PaletteManagerController.prototype.deselectCurrentPalette = function () {
var selectedItem = this.palettesList.querySelector('.' + SELECTED_CLASSNAME);
if (selectedItem) {
this.selectedPaletteId = null;
selectedItem.classList.remove(SELECTED_CLASSNAME);
}
};
ns.PaletteManagerController.prototype.revertChanges = function () {
var palette = this.getSelectedPalette();
var originalPalette = this.getPaletteById(palette.id, this.originalPalettes);
palette.name = originalPalette.name;
palette.colors = originalPalette.colors.slice(0);
this.createPaletteListMarkup();
this.selectPalette(palette.id);
};
ns.PaletteManagerController.prototype.deleteSelectedPalette = function () {
var palette = this.getSelectedPalette();
if (this.palettes.length > 1) {
if (window.confirm('Are you sure you want to delete "' + palette.name + '" ?')) {
this.removePaletteById(palette.id, this.palettes);
this.removePaletteById(palette.id, this.originalPalettes);
this.persistToLocalStorage();
this.createPaletteListMarkup();
this.selectPalette(this.palettes[0].id);
}
}
};
ns.PaletteManagerController.prototype.onPaletteListClick = function (event) {
var target = event.target;
if (target.dataset.paletteId) {
this.selectPalette(target.dataset.paletteId);
}
};
ns.PaletteManagerController.prototype.saveAll = function () {
this.palettes.forEach(function (palette) {
this.savePalette(palette.id);
}.bind(this));
this.createPaletteListMarkup();
this.selectPalette(this.getSelectedPalette().id);
};
ns.PaletteManagerController.prototype.savePalette = function (paletteId) {
var palette = this.getPaletteById(paletteId, this.palettes);
var originalPalette = this.getPaletteById(paletteId, this.originalPalettes);
if (originalPalette) {
originalPalette.name = palette.name;
originalPalette.colors = palette.colors;
} else {
this.originalPalettes.push(palette);
}
this.persistToLocalStorage();
};
ns.PaletteManagerController.prototype.savePaletteAndRedraw = function (paletteId) {
this.savePalette(paletteId);
this.createPaletteListMarkup();
this.selectPalette(this.getSelectedPalette().id);
};
ns.PaletteManagerController.prototype.persistToLocalStorage = function () {
window.localStorage.setItem('piskel.palettes', JSON.stringify(this.originalPalettes));
this.originalPalettes = this.retrieveUserPalettes();
$.publish(Events.PALETTE_LIST_UPDATED);
};
ns.PaletteManagerController.prototype.retrieveUserPalettes = function () {
var palettesString = window.localStorage.getItem('piskel.palettes');
return JSON.parse(palettesString) || [this.createPaletteObject('New palette')];
};
})();

View File

@ -1,41 +0,0 @@
(function () {
var ns = $.namespace("pskl.controller.settings");
ns.ApplicationSettingsController = function () {};
/**
* @public
*/
ns.ApplicationSettingsController.prototype.init = function() {
// Highlight selected background picker:
var backgroundClass = pskl.UserSettings.get(pskl.UserSettings.CANVAS_BACKGROUND);
$('#background-picker-wrapper')
.find('.background-picker[data-background-class=' + backgroundClass + ']')
.addClass('selected');
// Grid display and size
var gridWidth = pskl.UserSettings.get(pskl.UserSettings.GRID_WIDTH);
$('#grid-width').val(gridWidth);
$('#grid-width').change(this.onGridWidthChange.bind(this));
// Handle canvas background changes:
$('#background-picker-wrapper').click(this.onBackgroundClick.bind(this));
};
ns.ApplicationSettingsController.prototype.onGridWidthChange = function (evt) {
var width = $('#grid-width').val();
pskl.UserSettings.set(pskl.UserSettings.GRID_WIDTH, parseInt(width, 10));
};
ns.ApplicationSettingsController.prototype.onBackgroundClick = function (evt) {
var target = $(evt.target).closest('.background-picker');
if (target.length) {
var backgroundClass = target.data('background-class');
pskl.UserSettings.set(pskl.UserSettings.CANVAS_BACKGROUND, backgroundClass);
$('.background-picker').removeClass('selected');
target.addClass('selected');
}
};
})();

View File

@ -1,159 +0,0 @@
(function () {
var ns = $.namespace("pskl.controller.settings");
var URL_MAX_LENGTH = 60;
ns.GifExportController = function (piskelController) {
this.piskelController = piskelController;
};
/**
* List of Resolutions applicable for Gif export
* @static
* @type {Array} array of Objects {zoom:{Number}, default:{Boolean}}
*/
ns.GifExportController.RESOLUTIONS = [
{
'zoom' : 1
},{
'zoom' : 5
},{
'zoom' : 10,
'default' : true
},{
'zoom' : 20
}
];
ns.GifExportController.prototype.init = function () {
this.radioTemplate_ = pskl.utils.Template.get("gif-export-radio-template");
this.uploadStatusContainerEl = document.querySelectorAll(".gif-upload-status")[0];
this.previewContainerEl = document.querySelectorAll(".gif-export-preview")[0];
this.radioGroupEl = document.querySelectorAll(".gif-export-radio-group")[0];
this.uploadForm = $("[name=gif-export-upload-form]");
this.uploadForm.submit(this.onUploadFormSubmit_.bind(this));
this.createRadioElements_();
};
ns.GifExportController.prototype.onUploadFormSubmit_ = function (evt) {
evt.originalEvent.preventDefault();
var selectedZoom = this.getSelectedZoom_(),
fps = this.piskelController.getFPS(),
zoom = selectedZoom;
this.renderAsImageDataAnimatedGIF(zoom, fps, this.onGifRenderingCompleted_.bind(this));
};
ns.GifExportController.prototype.onGifRenderingCompleted_ = function (imageData) {
this.updatePreview_(imageData);
this.previewContainerEl.classList.add("preview-upload-ongoing");
pskl.app.imageUploadService.upload(imageData, this.onImageUploadCompleted_.bind(this));
};
ns.GifExportController.prototype.onImageUploadCompleted_ = function (imageUrl) {
this.updatePreview_(imageUrl);
this.updateStatus_(imageUrl);
this.previewContainerEl.classList.remove("preview-upload-ongoing");
};
ns.GifExportController.prototype.updatePreview_ = function (src) {
this.previewContainerEl.innerHTML = "<div><img style='max-width:240px;' src='"+src+"'/></div>";
};
ns.GifExportController.prototype.getSelectedZoom_ = function () {
var radiosColl = this.uploadForm.get(0).querySelectorAll("[name=gif-zoom-level]"),
radios = Array.prototype.slice.call(radiosColl,0);
var selectedRadios = radios.filter(function(radio) {return !!radio.checked;});
if (selectedRadios.length == 1) {
return selectedRadios[0].value;
} else {
throw "Unexpected error when retrieving selected zoom";
}
};
ns.GifExportController.prototype.createRadioElements_ = function () {
var resolutions = ns.GifExportController.RESOLUTIONS;
for (var i = 0 ; i < resolutions.length ; i++) {
var radio = this.createRadioForResolution_(resolutions[i]);
this.radioGroupEl.appendChild(radio);
}
};
ns.GifExportController.prototype.createRadioForResolution_ = function (resolution) {
var zoom = resolution.zoom;
var label = zoom*this.piskelController.getWidth() + "x" + zoom*this.piskelController.getHeight();
var value = zoom;
var radioHTML = pskl.utils.Template.replace(this.radioTemplate_, {value : value, label : label});
var radioEl = pskl.utils.Template.createFromHTML(radioHTML);
if (resolution['default']) {
var input = radioEl.getElementsByTagName("input")[0];
input.setAttribute("checked", "checked");
}
return radioEl;
};
ns.GifExportController.prototype.blobToBase64_ = function(blob, cb) {
var reader = new FileReader();
reader.onload = function() {
var dataUrl = reader.result;
cb(dataUrl);
};
reader.readAsDataURL(blob);
};
ns.GifExportController.prototype.renderAsImageDataAnimatedGIF = function(zoom, fps, cb) {
var gif = new window.GIF({
workers: 2,
quality: 10,
width: this.piskelController.getWidth()*zoom,
height: this.piskelController.getHeight()*zoom
});
for (var i = 0; i < this.piskelController.getFrameCount(); i++) {
var frame = this.piskelController.getFrameAt(i);
var canvasRenderer = new pskl.rendering.CanvasRenderer(frame, zoom);
var canvas = canvasRenderer.render();
gif.addFrame(canvas.getContext('2d'), {
delay: 1000 / fps
});
}
gif.on('finished', function(blob) {
this.blobToBase64_(blob, cb);
}.bind(this));
gif.render();
};
// FIXME : HORRIBLE COPY/PASTA
ns.GifExportController.prototype.updateStatus_ = function (imageUrl, error) {
if (imageUrl) {
var linkTpl = "<a class='image-link' href='{{link}}' target='_blank'>{{shortLink}}</a>";
var linkHtml = pskl.utils.Template.replace(linkTpl, {
link : imageUrl,
shortLink : this.shorten_(imageUrl, URL_MAX_LENGTH, '...')
});
this.uploadStatusContainerEl.innerHTML = 'Your image is now available at : ' + linkHtml;
} else {
// FIXME : Should display error message instead
}
};
ns.GifExportController.prototype.shorten_ = function (url, maxLength, suffix) {
if (url.length > maxLength) {
url = url.substring(0, maxLength);
url += suffix;
}
return url;
};
})();

View File

@ -1,172 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller.settings');
var DEFAULT_FILE_STATUS = 'No file selected ...';
var PREVIEW_HEIGHT = 60;
ns.ImportController = function (piskelController) {
this.piskelController = piskelController;
this.importedImage_ = null;
};
ns.ImportController.prototype.init = function () {
this.importForm = $('[name=import-form]');
this.hiddenFileInput = $('[name=file-upload-input]');
this.fileInputButton = $('.file-input-button');
this.fileInputStatus = $('.file-input-status');
this.fileInputStatus.html(DEFAULT_FILE_STATUS);
this.importPreview = $('.import-section-preview');
this.resizeWidth = $('[name=resize-width]');
this.resizeHeight = $('[name=resize-height]');
this.smoothResize = $('[name=smooth-resize-checkbox]');
this.submitButton = $('[name=import-submit]');
this.importForm.submit(this.onImportFormSubmit_.bind(this));
this.hiddenFileInput.change(this.onFileUploadChange_.bind(this));
this.fileInputButton.click(this.onFileInputClick_.bind(this));
this.resizeWidth.keyup(this.onResizeInputKeyUp_.bind(this, 'width'));
this.resizeHeight.keyup(this.onResizeInputKeyUp_.bind(this, 'height'));
};
ns.ImportController.prototype.reset_ = function () {
this.importForm.get(0).reset();
this.fileInputStatus.html(DEFAULT_FILE_STATUS);
$.publish(Events.CLOSE_SETTINGS_DRAWER);
};
ns.ImportController.prototype.onResizeInputKeyUp_ = function (from, evt) {
if (this.importedImage_) {
this.synchronizeResizeFields_(evt.target.value, from);
}
};
ns.ImportController.prototype.synchronizeResizeFields_ = function (value, from) {
value = parseInt(value, 10);
if (isNaN(value)) {
value = 0;
}
var height = this.importedImage_.height, width = this.importedImage_.width;
if (from === 'width') {
this.resizeHeight.val(Math.round(value * height / width));
} else {
this.resizeWidth.val(Math.round(value * width / height));
}
};
ns.ImportController.prototype.onImportFormSubmit_ = function (evt) {
evt.originalEvent.preventDefault();
this.importImageToPiskel_();
};
ns.ImportController.prototype.onFileUploadChange_ = function (evt) {
this.importFromFile_();
};
ns.ImportController.prototype.onFileInputClick_ = function (evt) {
this.hiddenFileInput.click();
};
ns.ImportController.prototype.importFromFile_ = function () {
var files = this.hiddenFileInput.get(0).files;
if (files.length == 1) {
var file = files[0];
if (this.isImage_(file)) {
this.readImageFile_(file);
this.enableDisabledSections_();
} else {
this.reset_();
throw 'File is not an image : ' + file.type;
}
}
};
ns.ImportController.prototype.enableDisabledSections_ = function () {
this.resizeWidth.removeAttr('disabled');
this.resizeHeight.removeAttr('disabled');
this.smoothResize.removeAttr('disabled');
this.submitButton.removeAttr('disabled');
this.fileInputButton.removeClass('button-primary');
this.fileInputButton.blur();
$('.import-section-disabled').removeClass('import-section-disabled');
};
ns.ImportController.prototype.readImageFile_ = function (imageFile) {
pskl.utils.FileUtils.readFile(imageFile, this.processImageSource_.bind(this));
};
/**
* Create an image from the given source (url or data-url), and onload forward to onImageLoaded
* TODO : should be a generic utility method, should take a callback
* @param {String} imageSource url or data-url, will be used as src for the image
*/
ns.ImportController.prototype.processImageSource_ = function (imageSource) {
this.importedImage_ = new Image();
this.importedImage_.onload = this.onImageLoaded_.bind(this);
this.importedImage_.src = imageSource;
};
ns.ImportController.prototype.onImageLoaded_ = function (evt) {
var w = this.importedImage_.width,
h = this.importedImage_.height;
var filePath = this.hiddenFileInput.val();
var fileName = this.extractFileNameFromPath_(filePath);
this.fileInputStatus.html(fileName);
this.resizeWidth.val(w);
this.resizeHeight.val(h);
this.importPreview.width('auto');
this.importPreview.html('');
this.importPreview.append(this.createImagePreview_());
};
ns.ImportController.prototype.createImagePreview_ = function () {
var image = document.createElement('IMG');
image.src = this.importedImage_.src;
image.setAttribute('height', PREVIEW_HEIGHT);
return image;
};
ns.ImportController.prototype.extractFileNameFromPath_ = function (path) {
var parts = [];
if (path.indexOf('/') !== -1) {
parts = path.split('/');
} else if (path.indexOf('\\') !== -1) {
parts = path.split('\\');
} else {
parts = [path];
}
return parts[parts.length-1];
};
ns.ImportController.prototype.importImageToPiskel_ = function () {
if (this.importedImage_) {
if (window.confirm('You are about to create a new Piskel, unsaved changes will be lost.')) {
var w = this.resizeWidth.val(),
h = this.resizeHeight.val(),
smoothing = !!this.smoothResize.prop('checked');
var image = pskl.utils.ImageResizer.resize(this.importedImage_, w, h, smoothing);
var frame = pskl.utils.FrameUtils.createFromImage(image);
var layer = pskl.model.Layer.fromFrames('Layer 1', [frame]);
var descriptor = new pskl.model.piskel.Descriptor('Imported piskel', '');
var piskel = pskl.model.Piskel.fromLayers([layer], descriptor);
pskl.app.piskelController.setPiskel(piskel);
pskl.app.animationController.setFPS(Constants.DEFAULT.FPS);
this.reset_();
}
}
};
ns.ImportController.prototype.isImage_ = function (file) {
return file.type.indexOf('image') === 0;
};
})();

View File

@ -1,70 +0,0 @@
(function () {
var ns = $.namespace("pskl.controller.settings");
ns.LocalStorageController = function () {};
/**
* @public
*/
ns.LocalStorageController.prototype.init = function() {
this.localStorageItemTemplate_ = pskl.utils.Template.get("local-storage-item-template");
this.service_ = pskl.app.localStorageService;
this.piskelsList = $('.local-piskels-list');
this.fillLocalPiskelsList_();
this.piskelsList.click(this.onPiskelsListClick_.bind(this));
};
ns.LocalStorageController.prototype.onPiskelsListClick_ = function (evt) {
var action = evt.target.getAttribute('data-action');
var name = evt.target.getAttribute('data-name');
if (action === 'load') {
if (window.confirm('This will erase your current piskel. Continue ?')) {
this.service_.load(name);
$.publish(Events.CLOSE_SETTINGS_DRAWER);
}
} else if (action === 'delete') {
if (window.confirm('This will permanently DELETE this piskel from your computer. Continue ?')) {
this.service_.remove(name);
$.publish(Events.CLOSE_SETTINGS_DRAWER);
}
}
};
ns.LocalStorageController.prototype.fillLocalPiskelsList_ = function () {
var html = "";
var keys = this.service_.getKeys();
var pad = function (num) {
if (num < 10) {
return "0" + num;
} else {
return "" + num;
}
};
keys.sort(function (k1, k2) {
if (k1.date < k2.date) {return 1;}
if (k1.date > k2.date) {return -1;}
return 0;
});
keys.forEach((function (key) {
var date = new Date(key.date);
var formattedDate = pskl.utils.Template.replace("{{Y}}/{{M}}/{{D}} {{H}}:{{m}}", {
Y : date.getFullYear(),
M : pad(date.getMonth() + 1),
D : pad(date.getDate()),
H : pad(date.getHours()),
m : pad(date.getMinutes())
});
html += pskl.utils.Template.replace(this.localStorageItemTemplate_, {name : key.name, date : formattedDate});
}).bind(this));
var tableBody_ = this.piskelsList.get(0).tBodies[0];
tableBody_.innerHTML = html;
};
})();

View File

@ -1,63 +0,0 @@
(function () {
var ns = $.namespace("pskl.controller.settings");
var URL_MAX_LENGTH = 60;
ns.PngExportController = function (piskelController) {
this.piskelController = piskelController;
};
ns.PngExportController.prototype.init = function () {
this.previewContainerEl = document.querySelectorAll(".png-export-preview")[0];
this.uploadStatusContainerEl = document.querySelectorAll(".png-upload-status")[0];
this.uploadForm = $("[name=png-export-upload-form]");
this.uploadForm.submit(this.onUploadFormSubmit_.bind(this));
this.updatePreview_(this.getFramesheetAsBase64Png());
};
ns.PngExportController.prototype.onUploadFormSubmit_ = function (evt) {
evt.originalEvent.preventDefault();
this.previewContainerEl.classList.add("preview-upload-ongoing");
pskl.app.imageUploadService.upload(this.getFramesheetAsBase64Png(), this.onImageUploadCompleted_.bind(this));
};
ns.PngExportController.prototype.getFramesheetAsBase64Png = function () {
var renderer = new pskl.rendering.PiskelRenderer(this.piskelController);
var framesheetCanvas = renderer.renderAsCanvas();
return framesheetCanvas.toDataURL("image/png");
};
ns.PngExportController.prototype.onImageUploadCompleted_ = function (imageUrl) {
this.updatePreview_(imageUrl);
this.updateStatus_(imageUrl);
this.previewContainerEl.classList.remove("preview-upload-ongoing");
};
ns.PngExportController.prototype.updateStatus_ = function (imageUrl, error) {
if (imageUrl) {
var linkTpl = "<a class='image-link' href='{{link}}' target='_blank'>{{shortLink}}</a>";
var linkHtml = pskl.utils.Template.replace(linkTpl, {
link : imageUrl,
shortLink : this.shorten_(imageUrl, URL_MAX_LENGTH, '...')
});
this.uploadStatusContainerEl.innerHTML = 'Your image is now available at : ' + linkHtml;
} else {
// FIXME : Should display error message instead
}
};
ns.PngExportController.prototype.updatePreview_ = function (src) {
this.previewContainerEl.innerHTML = "<img class='light-picker-background' style='max-width:240px;' src='"+src+"'/>";
};
ns.PngExportController.prototype.shorten_ = function (url, maxLength, suffix) {
if (url.length > maxLength) {
url = url.substring(0, maxLength);
url += suffix;
}
return url;
};
})();

View File

@ -1,58 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller.settings');
ns.ResizeController = function (piskelController) {
this.piskelController = piskelController;
};
ns.ResizeController.prototype.init = function () {
this.resizeWidth = $('[name=resize-width]');
this.resizeHeight = $('[name=resize-height]');
this.resizeWidth.val(this.piskelController.getWidth());
this.resizeHeight.val(this.piskelController.getHeight());
this.cancelButton = $('.resize-cancel-button');
this.cancelButton.click(this.onCancelButtonClicked_.bind(this));
this.resizeForm = $("[name=resize-form]");
this.resizeForm.submit(this.onResizeFormSubmit_.bind(this));
};
ns.ResizeController.prototype.onResizeFormSubmit_ = function (evt) {
evt.originalEvent.preventDefault();
var width = parseInt(this.resizeWidth.val(), 10);
var height = parseInt(this.resizeHeight.val(), 10);
var layers = [];
var fromLayers = this.piskelController.getLayers();
for (var i = 0 ; i < fromLayers.length ; i++) {
var frames = [];
var fromFrames = fromLayers[i].getFrames();
for (var j = 0 ; j < fromFrames.length ; j++) {
var frame = new pskl.model.Frame(width, height);
this.copyFromFrameToFrame(fromFrames[j], frame);
frames.push(frame);
}
var layer = pskl.model.Layer.fromFrames(fromLayers[i].getName(), frames);
layers.push(layer);
}
var piskel = pskl.model.Piskel.fromLayers(layers, this.piskelController.piskel.getDescriptor());
pskl.app.piskelController.setPiskel(piskel);
$.publish(Events.CLOSE_SETTINGS_DRAWER);
};
ns.ResizeController.prototype.copyFromFrameToFrame = function (from, to) {
from.forEachPixel(function (color, x, y) {
if (x < to.getWidth() && y < to.getHeight()) {
to.setPixel(x, y, color);
}
});
};
ns.ResizeController.prototype.onCancelButtonClicked_ = function (evt) {
$.publish(Events.CLOSE_SETTINGS_DRAWER);
};
})();

View File

@ -1,115 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller.settings');
ns.SaveController = function (piskelController) {
this.piskelController = piskelController;
};
/**
* @public
*/
ns.SaveController.prototype.init = function () {
this.saveForm = $('form[name=save-form]');
this.nameInput = $('#save-name');
this.descriptionInput = $('#save-description');
this.isPublicCheckbox = $('input[name=save-public-checkbox]');
this.saveCloudButton = $('#save-cloud-button');
this.saveLocalButton = $('#save-local-button');
// Only available in app-engine mode ...
this.piskelName = $('.piskel-name').get(0);
this.status = $('#save-status');
var descriptor = this.piskelController.piskel.getDescriptor();
this.nameInput.val(descriptor.name);
this.descriptionInput.val(descriptor.description);
this.isPublicCheckbox.prop('checked', descriptor.isPublic);
if (!pskl.app.isLoggedIn()) {
this.saveCloudButton.attr('disabled', 'disabled');
this.status.html('You are not logged in. Only Local Save is available.');
} else {
this.saveForm.submit(this.onSaveFormSubmit_.bind(this));
}
this.saveLocalButton.click(this.onSaveLocalClick_.bind(this));
};
ns.SaveController.prototype.onSaveFormSubmit_ = function (evt) {
evt.preventDefault();
evt.stopPropagation();
var name = this.getName();
var description = this.getDescription();
var isPublic = !!this.isPublicCheckbox.prop('checked');
var descriptor = new pskl.model.piskel.Descriptor(name, description, isPublic);
this.piskelController.piskel.setDescriptor(descriptor);
this.beforeSaving_();
pskl.app.store({
success : this.onSaveSuccess_.bind(this),
error : this.onSaveError_.bind(this),
after : this.afterSaving_.bind(this)
});
};
ns.SaveController.prototype.onSaveLocalClick_ = function (evt) {
var localStorageService = pskl.app.localStorageService;
var isOk = true;
var name = this.getName();
var description = this.getDescription();
if (localStorageService.getPiskel(name)) {
isOk = window.confirm('There is already a piskel saved as ' + name + '. Override ?');
}
if (isOk) {
this.beforeSaving_();
localStorageService.save(name, description, pskl.app.piskelController.serialize());
window.setTimeout(function () {
this.onSaveSuccess_();
this.afterSaving_();
}.bind(this), 1000);
}
};
ns.SaveController.prototype.getName = function () {
return this.nameInput.val();
};
ns.SaveController.prototype.getDescription = function () {
return this.descriptionInput.val();
};
ns.SaveController.prototype.beforeSaving_ = function () {
this.saveCloudButton.attr('disabled', true);
this.status.html('Saving ...');
if (this.piskelName) {
this.piskelName.classList.add('piskel-name-saving');
}
};
ns.SaveController.prototype.onSaveSuccess_ = function () {
$.publish(Events.CLOSE_SETTINGS_DRAWER);
$.publish(Events.SHOW_NOTIFICATION, [{"content": "Successfully saved !"}]);
$.publish(Events.PISKEL_SAVED);
};
ns.SaveController.prototype.onSaveError_ = function (status) {
$.publish(Events.SHOW_NOTIFICATION, [{"content": "Saving failed ("+status+")"}]);
};
ns.SaveController.prototype.afterSaving_ = function () {
this.saveCloudButton.attr('disabled', false);
this.status.html('');
if (this.piskelName) {
this.piskelName.classList.remove('piskel-name-saving');
}
window.setTimeout($.publish.bind($, Events.HIDE_NOTIFICATION), 2000);
};
})();

View File

@ -1,100 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller.settings');
var settings = {
'user' : {
template : 'templates/settings/application.html',
controller : ns.ApplicationSettingsController
},
'resize' : {
template : 'templates/settings/resize.html',
controller : ns.ResizeController
},
'gif' : {
template : 'templates/settings/export-gif.html',
controller : ns.GifExportController
},
'png' : {
template : 'templates/settings/export-png.html',
controller : ns.PngExportController
},
'import' : {
template : 'templates/settings/import.html',
controller : ns.ImportController
},
'localstorage' : {
template : 'templates/settings/localstorage.html',
controller : ns.LocalStorageController
},
'save' : {
template : 'templates/settings/save.html',
controller : ns.SaveController
}
};
var SEL_SETTING_CLS = 'has-expanded-drawer';
var EXP_DRAWER_CLS = 'expanded';
ns.SettingsController = function (piskelController) {
this.piskelController = piskelController;
this.drawerContainer = document.getElementById('drawer-container');
this.settingsContainer = $('[data-pskl-controller=settings]');
this.isExpanded = false;
this.currentSetting = null;
};
/**
* @public
*/
ns.SettingsController.prototype.init = function() {
$('[data-setting]').click(this.onSettingIconClick.bind(this));
$('body').click(this.onBodyClick.bind(this));
$.subscribe(Events.CLOSE_SETTINGS_DRAWER, this.closeDrawer.bind(this));
};
ns.SettingsController.prototype.onSettingIconClick = function (evt) {
var el = evt.originalEvent.currentTarget;
var setting = el.getAttribute('data-setting');
if (this.currentSetting != setting) {
this.loadSetting(setting);
} else {
this.closeDrawer();
}
evt.originalEvent.stopPropagation();
evt.originalEvent.preventDefault();
};
ns.SettingsController.prototype.onBodyClick = function (evt) {
var target = evt.target;
var isInDrawerContainer = pskl.utils.Dom.isParent(target, this.drawerContainer);
var isInSettingsIcon = target.getAttribute('data-setting');
var isInSettingsContainer = isInDrawerContainer || isInSettingsIcon;
if (this.isExpanded && !isInSettingsContainer) {
this.closeDrawer();
}
};
ns.SettingsController.prototype.loadSetting = function (setting) {
this.drawerContainer.innerHTML = pskl.utils.Template.get(settings[setting].template);
(new settings[setting].controller(this.piskelController)).init();
this.settingsContainer.addClass(EXP_DRAWER_CLS);
$('.' + SEL_SETTING_CLS).removeClass(SEL_SETTING_CLS);
$('[data-setting='+setting+']').addClass(SEL_SETTING_CLS);
this.isExpanded = true;
this.currentSetting = setting;
};
ns.SettingsController.prototype.closeDrawer = function () {
this.settingsContainer.removeClass(EXP_DRAWER_CLS);
$('.' + SEL_SETTING_CLS).removeClass(SEL_SETTING_CLS);
this.isExpanded = false;
this.currentSetting = null;
};
})();

View File

@ -1,88 +0,0 @@
/**
* @provide pskl.drawingtools.BaseTool
*
* @require pskl.utils
*/
(function() {
var ns = $.namespace("pskl.drawingtools");
ns.BaseTool = function() {};
ns.BaseTool.prototype.applyToolAt = function(col, row, color, frame, overlay, event) {};
ns.BaseTool.prototype.moveToolAt = function(col, row, color, frame, overlay, event) {};
ns.BaseTool.prototype.moveUnactiveToolAt = function(col, row, color, frame, overlay, event) {
if (overlay.containsPixel(col, row)) {
if (!isNaN(this.highlightedPixelCol) &&
!isNaN(this.highlightedPixelRow) &&
(this.highlightedPixelRow != row ||
this.highlightedPixelCol != col)) {
// Clean the previously highlighted pixel:
overlay.clear();
}
// Show the current pixel targeted by the tool:
overlay.setPixel(col, row, Constants.TOOL_TARGET_HIGHLIGHT_COLOR);
this.highlightedPixelCol = col;
this.highlightedPixelRow = row;
}
};
ns.BaseTool.prototype.hideHighlightedPixel = function(overlay) {
if (this.highlightedPixelRow !== null && this.highlightedPixelCol !== null) {
try {
overlay.setPixel(this.highlightedPixelCol, this.highlightedPixelRow, Constants.TRANSPARENT_COLOR);
} catch (e) {
console.warn('ns.BaseTool.prototype.hideHighlightedPixel failed');
}
this.highlightedPixelRow = null;
this.highlightedPixelCol = null;
}
};
ns.BaseTool.prototype.releaseToolAt = function(col, row, color, frame, overlay, event) {};
/**
* Bresenham line algorihtm: Get an array of pixels from
* start and end coordinates.
*
* http://en.wikipedia.org/wiki/Bresenham's_line_algorithm
* http://stackoverflow.com/questions/4672279/bresenham-algorithm-in-javascript
*
* @private
*/
ns.BaseTool.prototype.getLinePixels_ = function(x0, x1, y0, y1) {
var pixels = [];
var dx = Math.abs(x1-x0);
var dy = Math.abs(y1-y0);
var sx = (x0 < x1) ? 1 : -1;
var sy = (y0 < y1) ? 1 : -1;
var err = dx-dy;
while(true){
// Do what you need to for this
pixels.push({"col": x0, "row": y0});
if ((x0==x1) && (y0==y1)) {
break;
}
var e2 = 2*err;
if (e2>-dy){
err -= dy;
x0 += sx;
}
if (e2 < dx) {
err += dx;
y0 += sy;
}
}
return pixels;
};
})();

View File

@ -1,85 +0,0 @@
/**
* @provide pskl.drawingtools.Circle
*
* @require pskl.utils
*/
(function() {
var ns = $.namespace("pskl.drawingtools");
ns.Circle = function() {
this.toolId = "tool-circle";
this.helpText = "Circle tool";
// Circle's first point coordinates (set in applyToolAt)
this.startCol = null;
this.startRow = null;
};
pskl.utils.inherit(ns.Circle, ns.BaseTool);
/**
* @override
*/
ns.Circle.prototype.applyToolAt = function(col, row, color, frame, overlay, event) {
this.startCol = col;
this.startRow = row;
// Drawing the first point of the rectangle in the fake overlay canvas:
overlay.setPixel(col, row, color);
};
ns.Circle.prototype.moveToolAt = function(col, row, color, frame, overlay, event) {
overlay.clear();
if(color == Constants.TRANSPARENT_COLOR) {
color = Constants.SELECTION_TRANSPARENT_COLOR;
}
// draw in overlay
this.drawCircle_(col, row, color, overlay);
};
/**
* @override
*/
ns.Circle.prototype.releaseToolAt = function(col, row, color, frame, overlay, event) {
overlay.clear();
if(frame.containsPixel(col, row)) { // cancel if outside of canvas
// draw in frame to finalize
this.drawCircle_(col, row, color, frame);
}
};
ns.Circle.prototype.drawCircle_ = function (col, row, color, targetFrame) {
var circlePoints = this.getCirclePixels_(this.startCol, this.startRow, col, row);
for(var i = 0; i< circlePoints.length; i++) {
// Change model:
targetFrame.setPixel(circlePoints[i].col, circlePoints[i].row, color);
}
};
ns.Circle.prototype.getCirclePixels_ = function (x0, y0, x1, y1) {
var coords = pskl.PixelUtils.getOrderedRectangleCoordinates(x0, y0, x1, y1);
var xC = (coords.x0 + coords.x1)/2;
var yC = (coords.y0 + coords.y1)/2;
var rX = coords.x1 - xC;
var rY = coords.y1 - yC;
var pixels = [];
var x, y, angle;
for (x = coords.x0 ; x < coords.x1 ; x++) {
angle = Math.acos((x - xC)/rX);
y = Math.round(rY * Math.sin(angle) + yC);
pixels.push({"col": x, "row": y});
pixels.push({"col": 2*xC - x, "row": 2*yC - y});
}
for (y = coords.y0 ; y < coords.y1 ; y++) {
angle = Math.asin((y - yC)/rY);
x = Math.round(rX * Math.cos(angle) + xC);
pixels.push({"col": x, "row": y});
pixels.push({"col": 2*xC - x, "row": 2*yC - y});
}
return pixels;
};
})();

View File

@ -1,30 +0,0 @@
/**
* @provide pskl.drawingtools.ColorPicker
*
* @require pskl.utils
*/
(function() {
var ns = $.namespace("pskl.drawingtools");
ns.ColorPicker = function() {
this.toolId = "tool-colorpicker";
this.helpText = "Color picker";
};
pskl.utils.inherit(ns.ColorPicker, ns.BaseTool);
/**
* @override
*/
ns.ColorPicker.prototype.applyToolAt = function(col, row, color, frame, overlay, event) {
if (frame.containsPixel(col, row)) {
var sampledColor = frame.getPixel(col, row);
if (event.button == Constants.LEFT_BUTTON) {
$.publish(Events.SELECT_PRIMARY_COLOR, [sampledColor]);
} else if (event.button == Constants.RIGHT_BUTTON) {
$.publish(Events.SELECT_SECONDARY_COLOR, [sampledColor]);
}
}
};
})();

View File

@ -1,23 +0,0 @@
/**
* @provide pskl.drawingtools.Eraser
*
* @require Constants
* @require pskl.utils
*/
(function() {
var ns = $.namespace("pskl.drawingtools");
ns.Eraser = function() {
this.toolId = "tool-eraser";
this.helpText = "Eraser tool";
};
pskl.utils.inherit(ns.Eraser, ns.SimplePen);
/**
* @override
*/
ns.Eraser.prototype.applyToolAt = function(col, row, color, frame, overlay, event) {
this.superclass.applyToolAt.call(this, col, row, Constants.TRANSPARENT_COLOR, frame, overlay, event);
};
})();

View File

@ -1,56 +0,0 @@
/**
* @provide pskl.drawingtools.Move
*
* @require pskl.utils
*/
(function() {
var ns = $.namespace("pskl.drawingtools");
ns.Move = function() {
this.toolId = ns.Move.TOOL_ID;
this.helpText = "Move tool";
// Stroke's first point coordinates (set in applyToolAt)
this.startCol = null;
this.startRow = null;
};
ns.Move.TOOL_ID = "tool-move";
pskl.utils.inherit(ns.Move, ns.BaseTool);
/**
* @override
*/
ns.Move.prototype.applyToolAt = function(col, row, color, frame, overlay, event) {
this.startCol = col;
this.startRow = row;
this.frameClone = frame.clone();
};
ns.Move.prototype.moveToolAt = function(col, row, color, frame, overlay, event) {
var colDiff = col - this.startCol, rowDiff = row - this.startRow;
this.shiftFrame(colDiff, rowDiff, frame, this.frameClone);
};
ns.Move.prototype.shiftFrame = function (colDiff, rowDiff, frame, reference) {
var color;
for (var col = 0 ; col < frame.getWidth() ; col++) {
for (var row = 0 ; row < frame.getHeight() ; row++) {
if (reference.containsPixel(col - colDiff, row - rowDiff)) {
color = reference.getPixel(col - colDiff, row - rowDiff);
} else {
color = Constants.TRANSPARENT_COLOR;
}
frame.setPixel(col, row, color);
}
}
};
/**
* @override
*/
ns.Move.prototype.releaseToolAt = function(col, row, color, frame, overlay, event) {
this.moveToolAt(col, row, color, frame, overlay);
};
})();

View File

@ -1,36 +0,0 @@
/**
* @provide pskl.drawingtools.PaintBucket
*
* @require pskl.utils
*/
(function() {
var ns = $.namespace("pskl.drawingtools");
ns.PaintBucket = function() {
this.toolId = "tool-paint-bucket";
this.helpText = "Paint bucket tool";
};
pskl.utils.inherit(ns.PaintBucket, ns.BaseTool);
/**
* @override
*/
ns.PaintBucket.prototype.applyToolAt = function(col, row, color, frame, overlay, event) {
pskl.PixelUtils.paintSimilarConnectedPixelsFromFrame(frame, col, row, color);
};
})();

View File

@ -1,59 +0,0 @@
/**
* @provide pskl.drawingtools.Rectangle
*
* @require pskl.utils
*/
(function() {
var ns = $.namespace("pskl.drawingtools");
ns.Rectangle = function() {
this.toolId = "tool-rectangle";
this.helpText = "Rectangle tool";
// Rectangle's first point coordinates (set in applyToolAt)
this.startCol = null;
this.startRow = null;
};
pskl.utils.inherit(ns.Rectangle, ns.BaseTool);
/**
* @override
*/
ns.Rectangle.prototype.applyToolAt = function(col, row, color, frame, overlay, event) {
this.startCol = col;
this.startRow = row;
// Drawing the first point of the rectangle in the fake overlay canvas:
overlay.setPixel(col, row, color);
};
ns.Rectangle.prototype.moveToolAt = function(col, row, color, frame, overlay, event) {
overlay.clear();
if(color == Constants.TRANSPARENT_COLOR) {
color = Constants.SELECTION_TRANSPARENT_COLOR;
}
// draw in overlay
this.drawRectangle_(col, row, color, overlay);
};
/**
* @override
*/
ns.Rectangle.prototype.releaseToolAt = function(col, row, color, frame, overlay, event) {
overlay.clear();
if(frame.containsPixel(col, row)) { // cancel if outside of canvas
// draw in frame to finalize
this.drawRectangle_(col, row, color, frame);
}
};
ns.Rectangle.prototype.drawRectangle_ = function (col, row, color, targetFrame) {
var strokePoints = pskl.PixelUtils.getBoundRectanglePixels(this.startCol, this.startRow, col, row);
for(var i = 0; i< strokePoints.length; i++) {
// Change model:
targetFrame.setPixel(strokePoints[i].col, strokePoints[i].row, color);
}
};
})();

View File

@ -1,49 +0,0 @@
/**
* @provide pskl.drawingtools.SimplePen
*
* @require pskl.utils
*/
(function() {
var ns = $.namespace("pskl.drawingtools");
ns.SimplePen = function() {
this.toolId = "tool-pen";
this.helpText = "Pen tool";
this.previousCol = null;
this.previousRow = null;
};
pskl.utils.inherit(ns.SimplePen, ns.BaseTool);
/**
* @override
*/
ns.SimplePen.prototype.applyToolAt = function(col, row, color, frame, overlay, event) {
if (frame.containsPixel(col, row)) {
frame.setPixel(col, row, color);
}
this.previousCol = col;
this.previousRow = row;
};
ns.SimplePen.prototype.moveToolAt = function(col, row, color, frame, overlay, event) {
if((Math.abs(col - this.previousCol) > 1) || (Math.abs(row - this.previousRow) > 1)) {
// The pen movement is too fast for the mousemove frequency, there is a gap between the
// current point and the previously drawn one.
// We fill the gap by calculating missing dots (simple linear interpolation) and draw them.
var interpolatedPixels = this.getLinePixels_(col, this.previousCol, row, this.previousRow);
for(var i=0, l=interpolatedPixels.length; i<l; i++) {
var coords = interpolatedPixels[i];
this.applyToolAt(coords.col, coords.row, color, frame, overlay);
}
}
else {
this.applyToolAt(col, row, color, frame, overlay);
}
this.previousCol = col;
this.previousRow = row;
};
})();

View File

@ -1,80 +0,0 @@
/**
* @provide pskl.drawingtools.Stroke
*
* @require pskl.utils
*/
(function() {
var ns = $.namespace("pskl.drawingtools");
ns.Stroke = function() {
this.toolId = "tool-stroke";
this.helpText = "Stroke tool";
// Stroke's first point coordinates (set in applyToolAt)
this.startCol = null;
this.startRow = null;
};
pskl.utils.inherit(ns.Stroke, ns.BaseTool);
/**
* @override
*/
ns.Stroke.prototype.applyToolAt = function(col, row, color, frame, overlay, event) {
this.startCol = col;
this.startRow = row;
// When drawing a stroke we don't change the model instantly, since the
// user can move his cursor to change the stroke direction and length
// dynamically. Instead we draw the (preview) stroke in a fake canvas that
// overlay the drawing canvas.
// We wait for the releaseToolAt callback to impact both the
// frame model and canvas rendering.
// The fake canvas where we will draw the preview of the stroke:
// Drawing the first point of the stroke in the fake overlay canvas:
overlay.setPixel(col, row, color);
};
ns.Stroke.prototype.moveToolAt = function(col, row, color, frame, overlay, event) {
overlay.clear();
// When the user moussemove (before releasing), we dynamically compute the
// pixel to draw the line and draw this line in the overlay canvas:
var strokePoints = this.getLinePixels_(this.startCol, col, this.startRow, row);
// Drawing current stroke:
for(var i = 0; i< strokePoints.length; i++) {
if(color == Constants.TRANSPARENT_COLOR) {
// When mousemoving the stroke tool, we draw in the canvas overlay above the drawing canvas.
// If the stroke color is transparent, we won't be
// able to see it during the movement.
// We set it to a semi-opaque white during the tool mousemove allowing to see colors below the stroke.
// When the stroke tool will be released, It will draw a transparent stroke,
// eg deleting the equivalent of a stroke.
color = Constants.SELECTION_TRANSPARENT_COLOR;
}
overlay.setPixel(strokePoints[i].col, strokePoints[i].row, color);
}
};
/**
* @override
*/
ns.Stroke.prototype.releaseToolAt = function(col, row, color, frame, overlay, event) {
// If the stroke tool is released outside of the canvas, we cancel the stroke:
// TODO: Mutualize this check in common method
if(frame.containsPixel(col, row)) {
// The user released the tool to draw a line. We will compute the pixel coordinate, impact
// the model and draw them in the drawing canvas (not the fake overlay anymore)
var strokePoints = this.getLinePixels_(this.startCol, col, this.startRow, row);
for(var i = 0; i< strokePoints.length; i++) {
// Change model:
frame.setPixel(strokePoints[i].col, strokePoints[i].row, color);
}
}
// For now, we are done with the stroke tool and don't need an overlay anymore:
overlay.clear();
};
})();

View File

@ -1,46 +0,0 @@
(function() {
var ns = $.namespace("pskl.drawingtools");
ns.VerticalMirrorPen = function() {
this.toolId = "tool-vertical-mirror-pen";
this.helpText = "vertical mirror pen tool";
this.swap = null;
this.mirroredPreviousCol = null;
this.mirroredPreviousRow = null;
};
pskl.utils.inherit(ns.VerticalMirrorPen, ns.SimplePen);
ns.VerticalMirrorPen.prototype.setMirrorContext = function() {
this.swap = this.previousCol;
this.previousCol = this.mirroredPreviousCol;
};
ns.VerticalMirrorPen.prototype.unsetMirrorContext = function() {
this.mirroredPreviousCol = this.previousCol;
this.previousCol = this.swap;
};
/**
* @override
*/
ns.VerticalMirrorPen.prototype.applyToolAt = function(col, row, color, frame, overlay, event) {
this.superclass.applyToolAt.call(this, col, row, color, frame, overlay);
var mirroredCol = this.getSymmetricCol_(col, frame);
this.mirroredPreviousCol = mirroredCol;
this.setMirrorContext();
this.superclass.applyToolAt.call(this, mirroredCol, row, color, frame, overlay);
this.unsetMirrorContext();
};
/**
* @private
*/
ns.VerticalMirrorPen.prototype.getSymmetricCol_ = function(col, frame) {
return frame.getWidth() - col - 1;
};
})();

View File

@ -1,167 +0,0 @@
/**
* @provide pskl.drawingtools.BaseSelect
*
* @require pskl.utils
*/
(function() {
var ns = $.namespace("pskl.drawingtools");
ns.BaseSelect = function() {
this.secondaryToolId = pskl.drawingtools.Move.TOOL_ID;
this.BodyRoot = $('body');
// Select's first point coordinates (set in applyToolAt)
this.startCol = null;
this.startRow = null;
};
pskl.utils.inherit(ns.BaseSelect, ns.BaseTool);
/**
* @override
*/
ns.BaseSelect.prototype.applyToolAt = function(col, row, color, frame, overlay, event) {
this.startCol = col;
this.startRow = row;
this.lastCol = col;
this.lastRow = row;
// The select tool can be in two different state.
// If the inital click of the tool is not on a selection, we go in "select"
// mode to create a selection.
// If the initial click is on a previous selection, we go in "moveSelection"
// mode to allow to move the selection by drag'n dropping it.
if(overlay.getPixel(col, row) != Constants.SELECTION_TRANSPARENT_COLOR) {
this.mode = "select";
this.onSelectStart_(col, row, color, frame, overlay);
}
else {
this.mode = "moveSelection";
this.onSelectionDragStart_(col, row, color, frame, overlay);
}
};
/**
* @override
*/
ns.BaseSelect.prototype.moveToolAt = function(col, row, color, frame, overlay, event) {
if(this.mode == "select") {
this.onSelect_(col, row, color, frame, overlay);
}
else if(this.mode == "moveSelection") {
this.onSelectionDrag_(col, row, color, frame, overlay);
}
};
/**
* @override
*/
ns.BaseSelect.prototype.releaseToolAt = function(col, row, color, frame, overlay, event) {
if(this.mode == "select") {
this.onSelectEnd_(col, row, color, frame, overlay);
} else if(this.mode == "moveSelection") {
this.onSelectionDragEnd_(col, row, color, frame, overlay);
}
};
ns.BaseSelect.prototype.hideHighlightedPixel = function () {
// not implemented for selection tools
};
/**
* If we mouseover the selection draw inside the overlay frame, show the 'move' cursor
* instead of the 'select' one. It indicates that we can move the selection by dragndroping it.
* @override
*/
ns.BaseSelect.prototype.moveUnactiveToolAt = function(col, row, color, frame, overlay, event) {
if(overlay.getPixel(col, row) != Constants.SELECTION_TRANSPARENT_COLOR) {
// We're hovering the selection, show the move tool:
this.BodyRoot.addClass(this.toolId);
this.BodyRoot.removeClass(this.secondaryToolId);
} else {
// We're not hovering the selection, show create selection tool:
this.BodyRoot.addClass(this.secondaryToolId);
this.BodyRoot.removeClass(this.toolId);
}
};
ns.BaseSelect.prototype.hideHighlightedPixel = function() {
// there is no highlighted pixel for selection tools, do nothing
};
/**
* For each pixel in the selection draw it in white transparent on the tool overlay
* @protected
*/
ns.BaseSelect.prototype.drawSelectionOnOverlay_ = function (selection, overlay) {
var pixels = selection.pixels;
for(var i=0, l=pixels.length; i<l; i++) {
overlay.setPixel(pixels[i].col, pixels[i].row, Constants.SELECTION_TRANSPARENT_COLOR);
}
};
/**
* Move the overlay frame filled with semi-transparent pixels that represent the selection.
* @private
*/
ns.BaseSelect.prototype.shiftOverlayFrame_ = function (colDiff, rowDiff, overlayFrame, reference) {
var color;
for (var col = 0 ; col < overlayFrame.getWidth() ; col++) {
for (var row = 0 ; row < overlayFrame.getHeight() ; row++) {
if (reference.containsPixel(col - colDiff, row - rowDiff)) {
color = reference.getPixel(col - colDiff, row - rowDiff);
} else {
color = Constants.TRANSPARENT_COLOR;
}
overlayFrame.setPixel(col, row, color);
}
}
};
// The list of callbacks to implement by specialized tools to implement the selection creation behavior.
/** @protected */
ns.BaseSelect.prototype.onSelectStart_ = function (col, row, color, frame, overlay) {};
/** @protected */
ns.BaseSelect.prototype.onSelect_ = function (col, row, color, frame, overlay) {};
/** @protected */
ns.BaseSelect.prototype.onSelectEnd_ = function (col, row, color, frame, overlay) {};
// The list of callbacks that define the drag'n drop behavior of the selection.
/** @private */
ns.BaseSelect.prototype.onSelectionDragStart_ = function (col, row, color, frame, overlay) {
// Since we will move the overlayFrame in which the current selection is rendered,
// we clone it to have a reference for the later shifting process.
this.overlayFrameReference = overlay.clone();
};
/** @private */
ns.BaseSelect.prototype.onSelectionDrag_ = function (col, row, color, frame, overlay) {
var deltaCol = col - this.lastCol;
var deltaRow = row - this.lastRow;
var colDiff = col - this.startCol, rowDiff = row - this.startRow;
// Shifting selection on overlay frame:
this.shiftOverlayFrame_(colDiff, rowDiff, overlay, this.overlayFrameReference);
// Update selection model:
$.publish(Events.SELECTION_MOVE_REQUEST, [deltaCol, deltaRow]);
this.lastCol = col;
this.lastRow = row;
};
/** @private */
ns.BaseSelect.prototype.onSelectionDragEnd_ = function (col, row, color, frame, overlay) {
this.onSelectionDrag_(col, row, color, frame, overlay);
};
})();

View File

@ -1,52 +0,0 @@
/**
* @provide pskl.drawingtools.RectangleSelect
*
* @require pskl.utils
*/
(function() {
var ns = $.namespace("pskl.drawingtools");
ns.RectangleSelect = function() {
this.toolId = "tool-rectangle-select";
this.helpText = "Rectangle selection tool";
ns.BaseSelect.call(this);
};
pskl.utils.inherit(ns.RectangleSelect, ns.BaseSelect);
/**
* @override
*/
ns.RectangleSelect.prototype.onSelectStart_ = function (col, row, color, frame, overlay) {
// Drawing the first point of the rectangle in the fake overlay canvas:
overlay.setPixel(col, row, color);
};
/**
* When creating the rectangle selection, we clear the current overlayFrame and
* redraw the current rectangle based on the orgin coordinate and
* the current mouse coordiinate in sprite.
* @override
*/
ns.RectangleSelect.prototype.onSelect_ = function (col, row, color, frame, overlay) {
overlay.clear();
if(this.startCol == col &&this.startRow == row) {
$.publish(Events.SELECTION_DISMISSED);
} else {
var selection = new pskl.selection.RectangularSelection(
this.startCol, this.startRow, col, row);
$.publish(Events.SELECTION_CREATED, [selection]);
this.drawSelectionOnOverlay_(selection, overlay);
}
};
/**
* @override
*/
ns.RectangleSelect.prototype.onSelectEnd_ = function (col, row, color, frame, overlay) {
this.onSelect_(col, row, color, frame, overlay);
};
})();

View File

@ -1,36 +0,0 @@
/**
* @provide pskl.drawingtools.ShapeSelect
*
* @require pskl.utils
*/
(function() {
var ns = $.namespace("pskl.drawingtools");
ns.ShapeSelect = function() {
this.toolId = "tool-shape-select";
this.helpText = "Shape selection tool";
ns.BaseSelect.call(this);
};
pskl.utils.inherit(ns.ShapeSelect, ns.BaseSelect);
/**
* For the shape select tool, you just need to click one time to create a selection.
* So we jsut need to implement onSelectStart_ (no need for onSelect_ & onSelectEnd_)
* @override
*/
ns.ShapeSelect.prototype.onSelectStart_ = function (col, row, color, frame, overlay) {
// Clean previous selection:
$.publish(Events.SELECTION_DISMISSED);
overlay.clear();
// From the pixel cliked, get shape using an algorithm similar to the paintbucket one:
var pixels = pskl.PixelUtils.getSimilarConnectedPixelsFromFrame(frame, col, row);
var selection = new pskl.selection.ShapeSelection(pixels);
$.publish(Events.SELECTION_CREATED, [selection]);
this.drawSelectionOnOverlay_(selection, overlay);
};
})();

BIN
js/lib/.DS_Store vendored

Binary file not shown.

View File

@ -1,275 +0,0 @@
/* ===========================================================
* bootstrap-tooltip.js v2.1.1
* http://twitter.github.com/bootstrap/javascript.html#tooltips
* Inspired by the original jQuery.tipsy by Jason Frame
* ===========================================================
* Copyright 2012 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ========================================================== */
!function ($) {
"use strict"; // jshint ;_;
/* TOOLTIP PUBLIC CLASS DEFINITION
* =============================== */
var Tooltip = function (element, options) {
this.init('tooltip', element, options)
}
Tooltip.prototype = {
constructor: Tooltip
, init: function (type, element, options) {
var eventIn
, eventOut
this.type = type
this.$element = $(element)
this.options = this.getOptions(options)
this.enabled = true
if (this.options.trigger == 'click') {
this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
} else if (this.options.trigger != 'manual') {
eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus'
eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur'
this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
}
this.options.selector ?
(this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
this.fixTitle()
}
, getOptions: function (options) {
options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data())
if (options.delay && typeof options.delay == 'number') {
options.delay = {
show: options.delay
, hide: options.delay
}
}
return options
}
, enter: function (e) {
var self = $(e.currentTarget)[this.type](this._options).data(this.type)
if (!self.options.delay || !self.options.delay.show) return self.show()
clearTimeout(this.timeout)
self.hoverState = 'in'
this.timeout = setTimeout(function() {
if (self.hoverState == 'in') self.show()
}, self.options.delay.show)
}
, leave: function (e) {
var self = $(e.currentTarget)[this.type](this._options).data(this.type)
if (this.timeout) clearTimeout(this.timeout)
if (!self.options.delay || !self.options.delay.hide) return self.hide()
self.hoverState = 'out'
this.timeout = setTimeout(function() {
if (self.hoverState == 'out') self.hide()
}, self.options.delay.hide)
}
, show: function () {
var $tip
, inside
, pos
, actualWidth
, actualHeight
, placement
, tp
if (this.hasContent() && this.enabled) {
$tip = this.tip()
this.setContent()
if (this.options.animation) {
$tip.addClass('fade')
}
placement = typeof this.options.placement == 'function' ?
this.options.placement.call(this, $tip[0], this.$element[0]) :
this.options.placement
inside = /in/.test(placement)
$tip
.remove()
.css({ top: 0, left: 0, display: 'block' })
.appendTo(inside ? this.$element : document.body)
pos = this.getPosition(inside)
actualWidth = $tip[0].offsetWidth
actualHeight = $tip[0].offsetHeight
switch (inside ? placement.split(' ')[1] : placement) {
case 'bottom':
tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
break
case 'top':
tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
break
case 'left':
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
break
case 'right':
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
break
}
$tip
.css(tp)
.addClass(placement)
.addClass('in')
}
}
, setContent: function () {
var $tip = this.tip()
, title = this.getTitle()
$tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
$tip.removeClass('fade in top bottom left right')
}
, hide: function () {
var that = this
, $tip = this.tip()
$tip.removeClass('in')
function removeWithAnimation() {
var timeout = setTimeout(function () {
$tip.off($.support.transition.end).remove()
}, 500)
$tip.one($.support.transition.end, function () {
clearTimeout(timeout)
$tip.remove()
})
}
$.support.transition && this.$tip.hasClass('fade') ?
removeWithAnimation() :
$tip.remove()
return this
}
, fixTitle: function () {
var $e = this.$element
if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
$e.attr('data-original-title', $e.attr('title') || '').removeAttr('title')
}
}
, hasContent: function () {
return this.getTitle()
}
, getPosition: function (inside) {
return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), {
width: this.$element[0].offsetWidth
, height: this.$element[0].offsetHeight
})
}
, getTitle: function () {
var title
, $e = this.$element
, o = this.options
title = $e.attr('data-original-title')
|| (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
return title
}
, tip: function () {
return this.$tip = this.$tip || $(this.options.template)
}
, validate: function () {
if (!this.$element[0].parentNode) {
this.hide()
this.$element = null
this.options = null
}
}
, enable: function () {
this.enabled = true
}
, disable: function () {
this.enabled = false
}
, toggleEnabled: function () {
this.enabled = !this.enabled
}
, toggle: function () {
this[this.tip().hasClass('in') ? 'hide' : 'show']()
}
, destroy: function () {
this.hide().$element.off('.' + this.type).removeData(this.type)
}
}
/* TOOLTIP PLUGIN DEFINITION
* ========================= */
$.fn.tooltip = function ( option ) {
return this.each(function () {
var $this = $(this)
, data = $this.data('tooltip')
, options = typeof option == 'object' && option
if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
if (typeof option == 'string') data[option]()
})
}
$.fn.tooltip.Constructor = Tooltip
$.fn.tooltip.defaults = {
animation: true
, placement: 'top'
, selector: false
, template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
, trigger: 'hover'
, title: ''
, delay: 0
, html: true
}
}(window.jQuery);

View File

@ -1 +0,0 @@
Bootstrap custom build containing only the tooltip component

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

9227
js/lib/jquery-1.8.0.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +0,0 @@
/* jQuery Tiny Pub/Sub - v0.7 - 10/27/2011
* http://benalman.com/
* Copyright (c) 2011 "Cowboy" Ben Alman; Licensed MIT, GPL */
(function($) {
var o = $({});
$.subscribe = function() {
//console.log("SUBSCRIBE: " + arguments[0]);
o.on.apply(o, arguments);
};
$.unsubscribe = function() {
o.off.apply(o, arguments);
};
$.publish = function() {
//console.log("PUBLISH: " + arguments[0]);
o.trigger.apply(o, arguments);
};
}(jQuery));

File diff suppressed because it is too large Load Diff

View File

@ -1,139 +0,0 @@
(function () {
var ns = $.namespace("pskl.model");
ns.Frame = function (width, height) {
if (width && height) {
this.width = width;
this.height = height;
this.pixels = ns.Frame.createEmptyPixelGrid_(width, height);
this.previousStates = [this.getPixels()];
this.stateIndex = 0;
} else {
throw 'Bad arguments in pskl.model.Frame constructor : ' + width + ', ' + height;
}
};
ns.Frame.fromPixelGrid = function (pixels) {
if (pixels.length && pixels[0].length) {
var w = pixels.length, h = pixels[0].length;
var frame = new pskl.model.Frame(w, h);
frame.setPixels(pixels);
return frame;
} else {
throw 'Bad arguments in pskl.model.Frame.fromPixelGrid : ' + pixels;
}
};
ns.Frame.createEmptyPixelGrid_ = function (width, height) {
var pixels = []; //new Array(width);
for (var columnIndex=0; columnIndex < width; columnIndex++) {
var columnArray = [];
for(var heightIndex = 0; heightIndex < height; heightIndex++) {
columnArray.push(Constants.TRANSPARENT_COLOR);
}
pixels[columnIndex] = columnArray;
}
return pixels;
};
ns.Frame.createEmptyFromFrame = function (frame) {
return new ns.Frame(frame.getWidth(), frame.getHeight());
};
ns.Frame.prototype.clone = function () {
var clone = new ns.Frame(this.width, this.height);
clone.setPixels(this.getPixels());
return clone;
};
/**
* Returns a copy of the pixels used by the frame
*/
ns.Frame.prototype.getPixels = function () {
return this.clonePixels_(this.pixels);
};
/**
* Copies the passed pixels into the frame.
*/
ns.Frame.prototype.setPixels = function (pixels) {
this.pixels = this.clonePixels_(pixels);
};
ns.Frame.prototype.clear = function () {
var pixels = ns.Frame.createEmptyPixelGrid_(this.getWidth(), this.getHeight());
this.setPixels(pixels);
};
/**
* Clone a set of pixels. Should be static utility method
* @private
*/
ns.Frame.prototype.clonePixels_ = function (pixels) {
var clonedPixels = [];
for (var col = 0 ; col < pixels.length ; col++) {
clonedPixels[col] = pixels[col].slice(0 , pixels[col].length);
}
return clonedPixels;
};
ns.Frame.prototype.serialize = function () {
return JSON.stringify(this.pixels);
};
ns.Frame.prototype.setPixel = function (col, row, color) {
this.pixels[col][row] = color;
};
ns.Frame.prototype.getPixel = function (col, row) {
return this.pixels[col][row];
};
ns.Frame.prototype.forEachPixel = function (callback) {
for (var col = 0 ; col < this.getWidth() ; col++) {
for (var row = 0 ; row < this.getHeight() ; row++) {
callback(this.getPixel(col, row), col, row);
}
}
};
ns.Frame.prototype.getWidth = function () {
return this.width;
};
ns.Frame.prototype.getHeight = function () {
return this.height;
};
ns.Frame.prototype.containsPixel = function (col, row) {
return col >= 0 && row >= 0 && col < this.pixels.length && row < this.pixels[0].length;
};
ns.Frame.prototype.saveState = function () {
// remove all states past current state
this.previousStates.length = this.stateIndex + 1;
// push new state
this.previousStates.push(this.getPixels());
// set the stateIndex to latest saved state
this.stateIndex = this.previousStates.length - 1;
};
ns.Frame.prototype.loadPreviousState = function () {
if (this.stateIndex > 0) {
this.stateIndex--;
this.setPixels(this.previousStates[this.stateIndex]);
}
};
ns.Frame.prototype.loadNextState = function () {
if (this.stateIndex < this.previousStates.length - 1) {
this.stateIndex++;
this.setPixels(this.previousStates[this.stateIndex]);
}
};
ns.Frame.prototype.isSameSize = function (otherFrame) {
return this.getHeight() == otherFrame.getHeight() && this.getWidth() == otherFrame.getWidth();
};
})();

View File

@ -1,95 +0,0 @@
(function () {
var ns = $.namespace('pskl.model');
ns.Layer = function (name) {
if (!name) {
throw 'Invalid arguments in Layer constructor : \'name\' is mandatory';
} else {
this.name = name;
this.frames = [];
}
};
/**
* Create a Layer instance from an already existing set a Frames
* @static
* @param {String} name layer's name
* @param {Array<pskl.model.Frame>} frames should all have the same dimensions
* @return {pskl.model.Layer}
*/
ns.Layer.fromFrames = function (name, frames) {
var layer = new ns.Layer(name);
frames.forEach(layer.addFrame.bind(layer));
return layer;
};
ns.Layer.prototype.getName = function () {
return this.name;
};
ns.Layer.prototype.getFrames = function () {
return this.frames;
};
ns.Layer.prototype.getFrameAt = function (index) {
return this.frames[index];
};
ns.Layer.prototype.addFrame = function (frame) {
this.frames.push(frame);
};
ns.Layer.prototype.addFrameAt = function (frame, index) {
this.frames.splice(index, 0, frame);
};
ns.Layer.prototype.removeFrame = function (frame) {
var index = this.frames.indexOf(frame);
this.removeFrameAt(index);
};
ns.Layer.prototype.removeFrameAt = function (index) {
if (this.frames[index]) {
this.frames.splice(index, 1);
} else {
throw 'Invalid index in removeFrameAt : ' + index + ' (size : ' + this.length() + ')';
}
};
ns.Layer.prototype.moveFrame = function (fromIndex, toIndex) {
var frame = this.frames.splice(fromIndex, 1)[0];
this.frames.splice(toIndex, 0, frame);
};
ns.Layer.prototype.swapFramesAt = function (fromIndex, toIndex) {
var fromFrame = this.frames[fromIndex];
var toFrame = this.frames[toIndex];
if (fromFrame && toFrame) {
this.frames[toIndex] = fromFrame;
this.frames[fromIndex] = toFrame;
} else {
console.log('frames', this.frames);
console.log('fromIndex', fromIndex, 'toIndex', toIndex);
throw 'Frame not found in moveFrameAt';
}
};
ns.Layer.prototype.duplicateFrame = function (frame) {
var index = this.frames.indexOf(frame);
this.duplicateFrameAt(index);
};
ns.Layer.prototype.duplicateFrameAt = function (index) {
var frame = this.frames[index];
if (frame) {
var clone = frame.clone();
this.addFrameAt(clone, index);
} else {
throw 'Frame not found in duplicateFrameAt';
}
};
ns.Layer.prototype.length = function () {
return this.frames.length;
};
})();

View File

@ -1,112 +0,0 @@
(function () {
var ns = $.namespace('pskl.model');
/**
* @constructor
* @param {Number} width
* @param {Number} height
* @param {String} name
* @param {String} description
*/
ns.Piskel = function (width, height, descriptor) {
if (width && height && descriptor) {
/** @type {Array} */
this.layers = [];
/** @type {Number} */
this.width = width;
/** @type {Number} */
this.height = height;
this.descriptor = descriptor;
} else {
throw 'Missing arguments in Piskel constructor : ' + Array.prototype.join.call(arguments, ",");
}
};
/**
* Create a piskel instance from an existing set of (non empty) layers
* Layers should all be synchronized : same number of frames, same dimensions
* @param {Array<pskl.model.Layer>} layers
* @return {pskl.model.Piskel}
*/
ns.Piskel.fromLayers = function (layers, descriptor) {
var piskel = null;
if (layers.length > 0 && layers[0].length() > 0) {
var sampleFrame = layers[0].getFrameAt(0);
piskel = new pskl.model.Piskel(sampleFrame.getWidth(), sampleFrame.getHeight(), descriptor);
layers.forEach(piskel.addLayer.bind(piskel));
} else {
throw 'Piskel.fromLayers expects array of non empty pskl.model.Layer as first argument';
}
return piskel;
};
ns.Piskel.prototype.getLayers = function () {
return this.layers;
};
ns.Piskel.prototype.getHeight = function () {
return this.height;
};
ns.Piskel.prototype.getWidth = function () {
return this.width;
};
ns.Piskel.prototype.getLayers = function () {
return this.layers;
};
ns.Piskel.prototype.getLayerAt = function (index) {
return this.layers[index];
};
ns.Piskel.prototype.getLayersByName = function (name) {
return this.layers.filter(function (l) {
return l.getName() == name;
});
};
ns.Piskel.prototype.addLayer = function (layer) {
this.layers.push(layer);
};
ns.Piskel.prototype.moveLayerUp = function (layer) {
var index = this.layers.indexOf(layer);
if (index > -1 && index < this.layers.length-1) {
this.layers[index] = this.layers[index+1];
this.layers[index+1] = layer;
}
};
ns.Piskel.prototype.moveLayerDown = function (layer) {
var index = this.layers.indexOf(layer);
if (index > 0) {
this.layers[index] = this.layers[index-1];
this.layers[index-1] = layer;
}
};
ns.Piskel.prototype.removeLayer = function (layer) {
var index = this.layers.indexOf(layer);
if (index != -1) {
this.layers.splice(index, 1);
}
};
ns.Piskel.prototype.removeLayerAt = function (index) {
this.layers.splice(index, 1);
};
ns.Piskel.prototype.getDescriptor = function () {
return this.descriptor;
};
ns.Piskel.prototype.setDescriptor = function (descriptor) {
this.descriptor = descriptor;
var appEngineEditorHeader = $('.piskel-name').html(this.descriptor.name);
};
})();

View File

@ -1,9 +0,0 @@
(function () {
var ns = $.namespace('pskl.model.piskel');
ns.Descriptor = function (name, description, isPublic) {
this.name = name;
this.description = description;
this.isPublic = isPublic;
};
})();

12
js/piskel-packaged-min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,22 +0,0 @@
(function () {
var ns = $.namespace('pskl.rendering');
ns.AbstractRenderer = function () {};
ns.AbstractRenderer.prototype.clear = Constants.ABSTRACT_FUNCTION;
ns.AbstractRenderer.prototype.getCoordinates = Constants.ABSTRACT_FUNCTION;
ns.AbstractRenderer.prototype.setGridWidth = Constants.ABSTRACT_FUNCTION;
ns.AbstractRenderer.prototype.getGridWidth = Constants.ABSTRACT_FUNCTION;
ns.AbstractRenderer.prototype.setZoom = Constants.ABSTRACT_FUNCTION;
ns.AbstractRenderer.prototype.getZoom = Constants.ABSTRACT_FUNCTION;
ns.AbstractRenderer.prototype.moveOffset = Constants.ABSTRACT_FUNCTION;
ns.AbstractRenderer.prototype.setOffset = Constants.ABSTRACT_FUNCTION;
ns.AbstractRenderer.prototype.getOffset = Constants.ABSTRACT_FUNCTION;
ns.AbstractRenderer.prototype.setDisplaySize = Constants.ABSTRACT_FUNCTION;
ns.AbstractRenderer.prototype.getDisplaySize = Constants.ABSTRACT_FUNCTION;
})();

View File

@ -1,43 +0,0 @@
(function () {
var ns = $.namespace("pskl.rendering");
ns.CanvasRenderer = function (frame, zoom) {
this.frame = frame;
this.zoom = zoom;
this.transparentColor_ = 'white';
};
/**
* Decide which color should be used to represent transparent pixels
* Default : white
* @param {String} color the color to use either as '#ABCDEF' or 'red' or 'rgb(x,y,z)' or 'rgba(x,y,z,a)'
*/
ns.CanvasRenderer.prototype.drawTransparentAs = function (color) {
this.transparentColor_ = color;
};
ns.CanvasRenderer.prototype.render = function () {
var canvas = this.createCanvas_();
var context = canvas.getContext('2d');
this.frame.forEachPixel(function (color, x, y) {
this.renderPixel_(color, x, y, context);
}.bind(this));
return canvas;
};
ns.CanvasRenderer.prototype.renderPixel_ = function (color, x, y, context) {
if(color == Constants.TRANSPARENT_COLOR) {
color = this.transparentColor_;
}
context.fillStyle = color;
context.fillRect(x * this.zoom, y * this.zoom, this.zoom, this.zoom);
};
ns.CanvasRenderer.prototype.createCanvas_ = function () {
var width = this.frame.getWidth() * this.zoom;
var height = this.frame.getHeight() * this.zoom;
return pskl.CanvasUtils.createCanvas(width, height);
};
})();

View File

@ -1,75 +0,0 @@
(function () {
var ns = $.namespace('pskl.rendering');
ns.CompositeRenderer = function () {
this.renderers = [];
};
pskl.utils.inherit(pskl.rendering.CompositeRenderer, pskl.rendering.AbstractRenderer);
ns.CompositeRenderer.prototype.add = function (renderer) {
this.renderers.push(renderer);
return this;
};
ns.CompositeRenderer.prototype.clear = function () {
this.renderers.forEach(function (renderer) {
renderer.clear();
});
};
ns.CompositeRenderer.prototype.setZoom = function (zoom) {
this.renderers.forEach(function (renderer) {
renderer.setZoom(zoom);
});
};
ns.CompositeRenderer.prototype.getZoom = function () {
return this.getSampleRenderer_().getZoom();
};
ns.CompositeRenderer.prototype.setDisplaySize = function (w, h) {
this.renderers.forEach(function (renderer) {
renderer.setDisplaySize(w, h);
});
};
ns.CompositeRenderer.prototype.getDisplaySize = function () {
return this.getSampleRenderer_().getDisplaySize();
};
ns.CompositeRenderer.prototype.moveOffset = function (x, y) {
this.renderers.forEach(function (renderer) {
renderer.moveOffset(x, y);
});
};
ns.CompositeRenderer.prototype.setOffset = function (x, y) {
this.renderers.forEach(function (renderer) {
renderer.setOffset(x, y);
});
};
ns.CompositeRenderer.prototype.getOffset = function () {
return this.getSampleRenderer_().getOffset();
};
ns.CompositeRenderer.prototype.setGridWidth = function (b) {
this.renderers.forEach(function (renderer) {
renderer.setGridWidth(b);
});
};
ns.CompositeRenderer.prototype.getGridWidth = function () {
return this.getSampleRenderer_().getGridWidth();
};
ns.CompositeRenderer.prototype.getSampleRenderer_ = function () {
if (this.renderers.length > 0) {
return this.renderers[0];
} else {
throw 'Renderer manager is empty';
}
};
})();

View File

@ -1,61 +0,0 @@
(function () {
var ns = $.namespace("pskl.rendering");
ns.DrawingLoop = function () {
this.requestAnimationFrame = this.getRequestAnimationFrameShim_();
this.isRunning = false;
this.previousTime = 0;
this.callbacks = [];
};
ns.DrawingLoop.prototype.addCallback = function (callback, scope, args) {
var callbackObj = {
fn : callback,
scope : scope,
args : args
};
this.callbacks.push(callbackObj);
return callbackObj;
};
ns.DrawingLoop.prototype.removeCallback = function (callbackObj) {
var index = this.callbacks.indexOf(callbackObj);
if (index != -1) {
this.callbacks.splice(index, 1);
}
};
ns.DrawingLoop.prototype.start = function () {
this.isRunning = true;
this.loop_();
};
ns.DrawingLoop.prototype.loop_ = function () {
var currentTime = Date.now();
var delta = currentTime - this.previousTime;
this.executeCallbacks_(delta);
this.previousTime = currentTime;
this.requestAnimationFrame.call(window, this.loop_.bind(this));
};
ns.DrawingLoop.prototype.executeCallbacks_ = function (deltaTime) {
for (var i = 0 ; i < this.callbacks.length ; i++) {
var cb = this.callbacks[i];
cb.fn.call(cb.scope, deltaTime, cb.args);
}
};
ns.DrawingLoop.prototype.stop = function () {
this.isRunning = false;
};
ns.DrawingLoop.prototype.getRequestAnimationFrameShim_ = function () {
var requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function (callback) { window.setTimeout(callback, 1000/60); };
return requestAnimationFrame;
};
})();

View File

@ -1,43 +0,0 @@
(function () {
var ns = $.namespace('pskl.rendering');
/**
* Render an array of frames
* @param {Array.<pskl.model.Frame>} frames
*/
ns.FramesheetRenderer = function (frames) {
if (frames.length > 0) {
this.frames = frames;
} else {
throw 'FramesheetRenderer : Invalid argument : frames is empty';
}
};
ns.FramesheetRenderer.prototype.renderAsCanvas = function () {
var canvas = this.createCanvas_();
for (var i = 0 ; i < this.frames.length ; i++) {
var frame = this.frames[i];
this.drawFrameInCanvas_(frame, canvas, i * frame.getWidth(), 0);
}
return canvas;
};
ns.FramesheetRenderer.prototype.drawFrameInCanvas_ = function (frame, canvas, offsetWidth, offsetHeight) {
var context = canvas.getContext('2d');
frame.forEachPixel(function (color, x, y) {
if(color != Constants.TRANSPARENT_COLOR) {
context.fillStyle = color;
context.fillRect(x + offsetWidth, y + offsetHeight, 1, 1);
}
});
};
ns.FramesheetRenderer.prototype.createCanvas_ = function () {
var sampleFrame = this.frames[0];
var count = this.frames.length;
var width = count * sampleFrame.getWidth();
var height = sampleFrame.getHeight();
return pskl.CanvasUtils.createCanvas(width, height);
};
})();

View File

@ -1,14 +0,0 @@
(function () {
var ns = $.namespace("pskl.rendering");
ns.PiskelRenderer = function (piskelController) {
var frames = [];
for (var i = 0 ; i < piskelController.getFrameCount() ; i++) {
frames.push(piskelController.getFrameAt(i));
}
ns.FramesheetRenderer.call(this, frames);
};
pskl.utils.inherit(ns.PiskelRenderer, ns.FramesheetRenderer);
})();

View File

@ -1,32 +0,0 @@
(function () {
var ns = $.namespace('pskl.rendering.frame');
/**
* FrameRenderer implementation that prevents unnecessary redraws.
* @param {HtmlElement} container HtmlElement to use as parentNode of the Frame
* @param {Object} renderingOptions
* @param {Array} classes array of strings to use for css classes
*/
ns.CachedFrameRenderer = function (container, renderingOptions, classes) {
pskl.rendering.frame.FrameRenderer.call(this, container, renderingOptions, classes);
this.serializedFrame = '';
};
pskl.utils.inherit(pskl.rendering.frame.CachedFrameRenderer, pskl.rendering.frame.FrameRenderer);
ns.CachedFrameRenderer.prototype.render = function (frame) {
var offset = this.getOffset();
var size = this.getDisplaySize();
var serializedFrame = [
this.getZoom(),
this.getGridWidth(),
offset.x, offset.y,
size.width, size.height,
frame.serialize()
].join('-');
if (this.serializedFrame != serializedFrame) {
this.serializedFrame = serializedFrame;
this.superclass.render.call(this, frame);
}
};
})();

View File

@ -1,265 +0,0 @@
(function () {
var ns = $.namespace("pskl.rendering.frame");
/**
* FrameRenderer will display a given frame inside a canvas element.
* @param {HtmlElement} container HtmlElement to use as parentNode of the Frame
* @param {Object} renderingOptions
* @param {Array} classes array of strings to use for css classes
*/
ns.FrameRenderer = function (container, renderingOptions, classes) {
this.defaultRenderingOptions = {
'supportGridRendering' : false,
'zoom' : 1
};
renderingOptions = $.extend(true, {}, this.defaultRenderingOptions, renderingOptions);
if(container === undefined) {
throw 'Bad FrameRenderer initialization. <container> undefined.';
}
if(isNaN(renderingOptions.zoom)) {
throw 'Bad FrameRenderer initialization. <zoom> not well defined.';
}
this.container = container;
this.zoom = renderingOptions.zoom;
this.offset = {
x : 0,
y : 0
};
this.margin = {
x : 0,
y : 0
};
this.supportGridRendering = renderingOptions.supportGridRendering;
this.classes = classes || [];
this.classes.push('canvas');
/**
* Off dom canvas, will be used to draw the frame at 1:1 ratio
* @type {HTMLElement}
*/
this.canvas = null;
/**
* Displayed canvas, scaled-up from the offdom canvas
* @type {HTMLElement}
*/
this.displayCanvas = null;
this.setDisplaySize(renderingOptions.width, renderingOptions.height);
this.setGridWidth(pskl.UserSettings.get(pskl.UserSettings.GRID_WIDTH));
this.updateBackgroundClass_(pskl.UserSettings.get(pskl.UserSettings.CANVAS_BACKGROUND));
$.subscribe(Events.USER_SETTINGS_CHANGED, $.proxy(this.onUserSettingsChange_, this));
};
pskl.utils.inherit(pskl.rendering.frame.FrameRenderer, pskl.rendering.AbstractRenderer);
ns.FrameRenderer.prototype.render = function (frame) {
if (frame) {
this.clear();
this.renderFrame_(frame);
}
};
ns.FrameRenderer.prototype.clear = function () {
pskl.CanvasUtils.clear(this.canvas);
pskl.CanvasUtils.clear(this.displayCanvas);
};
ns.FrameRenderer.prototype.setZoom = function (zoom) {
if (zoom > Constants.MINIMUM_ZOOM) {
// back up center coordinates
var centerX = this.offset.x + (this.displayWidth/(2*this.zoom));
var centerY = this.offset.y + (this.displayHeight/(2*this.zoom));
this.zoom = zoom;
// recenter
this.setOffset(
centerX - (this.displayWidth/(2*this.zoom)),
centerY - (this.displayHeight/(2*this.zoom))
);
}
};
ns.FrameRenderer.prototype.getZoom = function () {
return this.zoom;
};
ns.FrameRenderer.prototype.setDisplaySize = function (width, height) {
this.displayWidth = width;
this.displayHeight = height;
if (this.displayCanvas) {
$(this.displayCanvas).remove();
this.displayCanvas = null;
}
this.createDisplayCanvas_();
};
ns.FrameRenderer.prototype.getDisplaySize = function () {
return {
height : this.displayHeight,
width : this.displayWidth
};
};
ns.FrameRenderer.prototype.getOffset = function () {
return {
x : this.offset.x,
y : this.offset.y
};
};
ns.FrameRenderer.prototype.moveOffset = function (x, y) {
this.setOffset(this.offset.x + x, this.offset.y + y);
};
ns.FrameRenderer.prototype.setOffset = function (x, y) {
// TODO : provide frame size information to the FrameRenderer constructor
// here I first need to verify I have a 'canvas' which I can use to infer the frame information
// and then perform my boundaries checking. This sucks
if (this.canvas) {
var maxX = this.canvas.width - (this.displayWidth/this.zoom);
x = pskl.utils.Math.minmax(x, 0, maxX);
var maxY = this.canvas.height - (this.displayHeight/this.zoom);
y = pskl.utils.Math.minmax(y, 0, maxY);
}
this.offset.x = x;
this.offset.y = y;
};
ns.FrameRenderer.prototype.setGridWidth = function (value) {
this.gridWidth_ = value;
};
ns.FrameRenderer.prototype.getGridWidth = function () {
if (this.supportGridRendering) {
return this.gridWidth_;
} else {
return 0;
}
};
ns.FrameRenderer.prototype.updateMargins_ = function () {
var deltaX = this.displayWidth - (this.zoom * this.canvas.width);
this.margin.x = Math.max(0, deltaX) / 2;
var deltaY = this.displayHeight - (this.zoom * this.canvas.height);
this.margin.y = Math.max(0, deltaY) / 2;
};
ns.FrameRenderer.prototype.createDisplayCanvas_ = function () {
var height = this.displayHeight;
var width = this.displayWidth;
this.displayCanvas = pskl.CanvasUtils.createCanvas(width, height, this.classes);
if (true || this.zoom > 2) {
pskl.CanvasUtils.disableImageSmoothing(this.displayCanvas);
}
this.container.append(this.displayCanvas);
};
ns.FrameRenderer.prototype.onUserSettingsChange_ = function (evt, settingName, settingValue) {
if (settingName == pskl.UserSettings.CANVAS_BACKGROUND) {
this.updateBackgroundClass_(settingValue);
} else if (settingName == pskl.UserSettings.GRID_WIDTH) {
this.setGridWidth(settingValue);
}
};
ns.FrameRenderer.prototype.updateBackgroundClass_ = function (newClass) {
var currentClass = this.container.data('current-background-class');
if (currentClass) {
this.container.removeClass(currentClass);
}
this.container.addClass(newClass);
this.container.data('current-background-class', newClass);
};
ns.FrameRenderer.prototype.renderPixel_ = function (color, x, y, context) {
if(color != Constants.TRANSPARENT_COLOR) {
context.fillStyle = color;
context.fillRect(x, y, 1, 1);
}
};
/**
* Transform a screen pixel-based coordinate (relative to the top-left corner of the rendered
* frame) into a sprite coordinate in column and row.
* @public
*/
ns.FrameRenderer.prototype.getCoordinates = function(x, y) {
var containerOffset = this.container.offset();
x = x - containerOffset.left;
y = y - containerOffset.top;
// apply margins
x = x - this.margin.x;
y = y - this.margin.y;
var cellSize = this.zoom;
// apply frame offset
x = x + this.offset.x * cellSize;
y = y + this.offset.y * cellSize;
return {
x : Math.floor(x / cellSize),
y : Math.floor(y / cellSize)
};
};
/**
* @private
*/
ns.FrameRenderer.prototype.renderFrame_ = function (frame) {
if (!this.canvas || frame.getWidth() != this.canvas.width || frame.getHeight() != this.canvas.height) {
this.canvas = pskl.CanvasUtils.createCanvas(frame.getWidth(), frame.getHeight());
}
var context = this.canvas.getContext('2d');
for(var x = 0, width = frame.getWidth(); x < width; x++) {
for(var y = 0, height = frame.getHeight(); y < height; y++) {
var color = frame.getPixel(x, y);
this.renderPixel_(color, x, y, context);
}
}
this.updateMargins_();
context = this.displayCanvas.getContext('2d');
context.save();
if (this.canvas.width*this.zoom < this.displayCanvas.width) {
context.fillStyle = Constants.ZOOMED_OUT_BACKGROUND_COLOR;
context.fillRect(0,0,this.displayCanvas.width, this.displayCanvas.height);
}
context.translate(
this.margin.x-this.offset.x*this.zoom,
this.margin.y-this.offset.y*this.zoom
);
context.clearRect(0, 0, this.canvas.width*this.zoom, this.canvas.height*this.zoom);
var isIE10 = pskl.utils.UserAgent.isIE && pskl.utils.UserAgent.version === 10;
var gridWidth = this.getGridWidth();
var isGridEnabled = gridWidth > 0;
if (isGridEnabled || isIE10) {
var scaled = pskl.utils.ImageResizer.resizeNearestNeighbour(this.canvas, this.zoom, gridWidth);
context.drawImage(scaled, 0, 0);
} else {
context.scale(this.zoom, this.zoom);
context.drawImage(this.canvas, 0, 0);
}
context.restore();
};
})();

View File

@ -1,67 +0,0 @@
(function () {
var ns = $.namespace('pskl.rendering.layer');
ns.LayersRenderer = function (container, renderingOptions, piskelController) {
pskl.rendering.CompositeRenderer.call(this);
this.piskelController = piskelController;
// Do not use CachedFrameRenderers here, since the caching will be performed in the render method of LayersRenderer
this.belowRenderer = new pskl.rendering.frame.FrameRenderer(container, renderingOptions, ["layers-canvas", "layers-below-canvas"]);
this.aboveRenderer = new pskl.rendering.frame.FrameRenderer(container, renderingOptions, ["layers-canvas", "layers-above-canvas"]);
this.add(this.belowRenderer);
this.add(this.aboveRenderer);
this.serializedRendering = '';
};
pskl.utils.inherit(pskl.rendering.layer.LayersRenderer, pskl.rendering.CompositeRenderer);
ns.LayersRenderer.prototype.render = function () {
var offset = this.getOffset();
var size = this.getDisplaySize();
var layers = this.piskelController.getLayers();
var currentFrameIndex = this.piskelController.currentFrameIndex;
var currentLayerIndex = this.piskelController.currentLayerIndex;
var serializedRendering = [
this.getZoom(),
this.getGridWidth(),
offset.x,
offset.y,
size.width,
size.height,
currentFrameIndex,
currentLayerIndex,
layers.length
].join("-");
if (this.serializedRendering != serializedRendering) {
this.serializedRendering = serializedRendering;
this.clear();
var downLayers = layers.slice(0, currentLayerIndex);
if (downLayers.length > 0) {
var downFrame = this.getFrameForLayersAt_(currentFrameIndex, downLayers);
this.belowRenderer.render(downFrame);
}
var upLayers = layers.slice(currentLayerIndex + 1, layers.length);
if (upLayers.length > 0) {
var upFrame = this.getFrameForLayersAt_(currentFrameIndex, upLayers);
this.aboveRenderer.render(upFrame);
}
}
};
ns.LayersRenderer.prototype.getFrameForLayersAt_ = function (frameIndex, layers) {
var frames = layers.map(function (l) {
return l.getFrameAt(frameIndex);
});
return pskl.utils.FrameUtils.merge(frames);
};
})();

View File

@ -1,34 +0,0 @@
(function () {
var ns = $.namespace("pskl.selection");
ns.BaseSelection = function () {
this.reset();
};
ns.BaseSelection.prototype.reset = function () {
this.pixels = [];
this.hasPastedContent = false;
};
ns.BaseSelection.prototype.move = function (colDiff, rowDiff) {
var movedPixel, movedPixels = [];
for(var i=0, l=this.pixels.length; i<l; i++) {
movedPixel = this.pixels[i];
movedPixel.col += colDiff;
movedPixel.row += rowDiff;
movedPixels.push(movedPixel);
}
this.pixels = movedPixels;
};
ns.BaseSelection.prototype.fillSelectionFromFrame = function (targetFrame) {
var pixelWithCopiedColor;
for(var i=0, l=this.pixels.length; i<l; i++) {
pixelWithCopiedColor = this.pixels[i];
pixelWithCopiedColor.copiedColor =
targetFrame.getPixel(pixelWithCopiedColor.col, pixelWithCopiedColor.row);
}
this.hasPastedContent = true;
};
})();

View File

@ -1,9 +0,0 @@
(function () {
var ns = $.namespace("pskl.selection");
ns.RectangularSelection = function (x0, y0, x1, y1) {
this.pixels = pskl.PixelUtils.getRectanglePixels(x0, y0, x1, y1);
};
pskl.utils.inherit(ns.RectangularSelection, ns.BaseSelection);
})();

View File

@ -1,119 +0,0 @@
(function () {
var ns = $.namespace("pskl.selection");
ns.SelectionManager = function (piskelController) {
this.piskelController = piskelController;
this.currentSelection = null;
};
ns.SelectionManager.prototype.init = function () {
$.subscribe(Events.SELECTION_CREATED, $.proxy(this.onSelectionCreated_, this));
$.subscribe(Events.SELECTION_DISMISSED, $.proxy(this.onSelectionDismissed_, this));
$.subscribe(Events.SELECTION_MOVE_REQUEST, $.proxy(this.onSelectionMoved_, this));
pskl.app.shortcutService.addShortcut('ctrl+V', this.paste.bind(this));
pskl.app.shortcutService.addShortcut('ctrl+X', this.cut.bind(this));
pskl.app.shortcutService.addShortcut('ctrl+C', this.copy.bind(this));
pskl.app.shortcutService.addShortcut('del', this.erase.bind(this));
$.subscribe(Events.TOOL_SELECTED, $.proxy(this.onToolSelected_, this));
};
/**
* @private
*/
ns.SelectionManager.prototype.cleanSelection_ = function() {
if(this.currentSelection) {
this.currentSelection.reset();
}
};
/**
* @private
*/
ns.SelectionManager.prototype.onToolSelected_ = function(evt, tool) {
var isSelectionTool = tool instanceof pskl.drawingtools.BaseSelect;
if(!isSelectionTool) {
this.cleanSelection_();
}
};
/**
* @private
*/
ns.SelectionManager.prototype.onSelectionDismissed_ = function(evt) {
this.cleanSelection_();
};
ns.SelectionManager.prototype.erase = function () {
var pixels = this.currentSelection.pixels;
var currentFrame = this.piskelController.getCurrentFrame();
for(var i=0, l=pixels.length; i<l; i++) {
try {
currentFrame.setPixel(pixels[i].col, pixels[i].row, Constants.TRANSPARENT_COLOR);
} catch(e) {
// Catching out of frame's bound pixels without testing
}
}
};
ns.SelectionManager.prototype.cut = function() {
if(this.currentSelection) {
// Put cut target into the selection:
this.currentSelection.fillSelectionFromFrame(this.piskelController.getCurrentFrame());
this.erase();
}
else {
throw "Bad state for CUT callback in SelectionManager";
}
};
ns.SelectionManager.prototype.paste = function() {
if(this.currentSelection && this.currentSelection.hasPastedContent) {
var pixels = this.currentSelection.pixels;
var currentFrame = this.piskelController.getCurrentFrame();
for(var i=0, l=pixels.length; i<l; i++) {
try {
currentFrame.setPixel(
pixels[i].col, pixels[i].row,
pixels[i].copiedColor);
} catch(e) {
// Catching out of frame's bound pixels without testing
}
}
}
};
ns.SelectionManager.prototype.copy = function() {
if(this.currentSelection && this.piskelController.getCurrentFrame()) {
this.currentSelection.fillSelectionFromFrame(this.piskelController.getCurrentFrame());
} else {
throw "Bad state for CUT callback in SelectionManager";
}
};
/**
* @private
*/
ns.SelectionManager.prototype.onSelectionCreated_ = function(evt, selection) {
if(selection) {
this.currentSelection = selection;
} else {
throw "No selection set in SelectionManager";
}
};
/**
* @private
*/
ns.SelectionManager.prototype.onSelectionMoved_ = function(evt, colDiff, rowDiff) {
if(this.currentSelection) {
this.currentSelection.move(colDiff, rowDiff);
}
else {
throw "Bad state: No currentSelection set when trying to move it in SelectionManager";
}
};
})();

View File

@ -1,9 +0,0 @@
(function () {
var ns = $.namespace("pskl.selection");
ns.ShapeSelection = function (pixels) {
this.pixels = pixels;
};
pskl.utils.inherit(ns.ShapeSelection, ns.BaseSelection);
})();

View File

@ -1,49 +0,0 @@
(function () {
var ns = $.namespace('pskl.service');
ns.AppEngineStorageService = function (piskelController) {
this.piskelController = piskelController;
};
ns.AppEngineStorageService.prototype.init = function () {};
ns.AppEngineStorageService.prototype.store = function (callbacks) {
var formData = this.prepareFormData_();
var xhr = new XMLHttpRequest();
xhr.open('POST', Constants.APPENGINE.URL.SAVE, true);
xhr.onload = function(e) {
if (this.status == 200) {
callbacks.success();
callbacks.after();
} else {
this.onerror(e);
}
};
xhr.onerror = function(e) {
callbacks.error(this.status);
callbacks.after();
};
xhr.send(formData);
};
ns.AppEngineStorageService.prototype.prepareFormData_ = function () {
var piskel = this.piskelController.piskel;
var descriptor = piskel.getDescriptor();
var formData = new FormData();
formData.append('framesheet', this.piskelController.serialize());
formData.append('fps', this.piskelController.getFPS());
formData.append('name', descriptor.name);
formData.append('description', descriptor.description);
if (descriptor.isPublic) {
formData.append('public', true);
}
formData.append('frames', this.piskelController.getFrameCount());
formData.append('first_frame_as_png', pskl.app.getFirstFrameAsPng());
formData.append('framesheet_as_png', pskl.app.getFramesheetAsPng());
return formData;
};
})();

View File

@ -1,31 +0,0 @@
(function () {
var ns = $.namespace('pskl.service');
ns.GithubStorageService = function (piskelController) {
this.piskelController = piskelController;
};
ns.GithubStorageService.prototype.init = function () {};
ns.GithubStorageService.prototype.store = function (callbacks) {
var xhr = new XMLHttpRequest();
var formData = new FormData();
formData.append('framesheet_content', this.piskelController.serialize());
formData.append('fps_speed', this.piskelController.getFPS());
xhr.open('POST', Constants.STATIC.URL.SAVE, true);
xhr.onload = function(e) {
if (this.status == 200) {
var baseUrl = window.location.href.replace(window.location.search, "");
window.location.href = baseUrl + "?frameId=" + this.responseText;
} else {
this.onerror(e);
}
};
xhr.onerror = function(e) {
$.publish(Events.SHOW_NOTIFICATION, [{"content": "Saving failed ("+this.status+")"}]);
};
xhr.send(formData);
};
})();

View File

@ -1,35 +0,0 @@
(function () {
var ns = $.namespace("pskl.service");
ns.HistoryService = function (piskelController) {
this.piskelController = piskelController;
this.saveState__b = this.saveState.bind(this);
};
ns.HistoryService.prototype.init = function () {
$.subscribe(Events.PISKEL_RESET, this.saveState__b);
$.subscribe(Events.TOOL_RELEASED, this.saveState__b);
pskl.app.shortcutService.addShortcut('ctrl+Z', this.undo.bind(this));
pskl.app.shortcutService.addShortcut('ctrl+Y', this.redo.bind(this));
};
ns.HistoryService.prototype.saveState = function () {
this.piskelController.getCurrentFrame().saveState();
};
ns.HistoryService.prototype.undo = function () {
this.piskelController.getCurrentFrame().loadPreviousState();
$.unsubscribe(Events.PISKEL_RESET, this.saveState__b);
$.publish(Events.PISKEL_RESET);
$.subscribe(Events.PISKEL_RESET, this.saveState__b);
};
ns.HistoryService.prototype.redo = function () {
this.piskelController.getCurrentFrame().loadNextState();
$.unsubscribe(Events.PISKEL_RESET, this.saveState__b);
$.publish(Events.PISKEL_RESET);
$.subscribe(Events.PISKEL_RESET, this.saveState__b);
};
})();

View File

@ -1,28 +0,0 @@
(function () {
var ns = $.namespace("pskl.service");
ns.ImageUploadService = function () {};
ns.ImageUploadService.prototype.init = function () {};
/**
* Upload a base64 image data to distant service. If successful, will call provided callback with the image URL as first argument;
* @param {String} imageData base64 image data (such as the return value of canvas.toDataUrl())
* @param {Function} cbSuccess success callback. 1st argument will be the uploaded image URL
* @param {Function} cbError error callback
*/
ns.ImageUploadService.prototype.upload = function (imageData, cbSuccess, cbError) {
var xhr = new XMLHttpRequest();
var formData = new FormData();
formData.append('data', imageData);
xhr.open('POST', Constants.IMAGE_SERVICE_UPLOAD_URL, true);
xhr.onload = function (e) {
if (this.status == 200) {
var imageUrl = Constants.IMAGE_SERVICE_GET_URL + this.responseText;
cbSuccess(imageUrl);
} else {
cbError();
}
};
xhr.send(formData);
};
})();

View File

@ -1,80 +0,0 @@
(function () {
var ns = $.namespace("pskl.service");
ns.LocalStorageService = function (piskelController) {
if(piskelController === undefined) {
throw "Bad LocalStorageService initialization: <undefined piskelController>";
}
this.piskelController = piskelController;
};
ns.LocalStorageService.prototype.init = function() {};
// localStorage.setItem('piskel_bkp', pskl.app.piskelController.serialize())
ns.LocalStorageService.prototype.save = function(name, description, piskel) {
this.removeFromKeys_(name);
this.addToKeys_(name, description, Date.now());
window.localStorage.setItem('piskel.' + name, piskel);
};
ns.LocalStorageService.prototype.load = function(name) {
var piskelString = this.getPiskel(name);
var key = this.getKey_(name);
pskl.utils.serialization.Deserializer.deserialize(JSON.parse(piskelString), function (piskel) {
piskel.setDescriptor(new pskl.model.piskel.Descriptor(name, key.description, true));
pskl.app.piskelController.setPiskel(piskel);
});
};
ns.LocalStorageService.prototype.remove = function(name) {
this.removeFromKeys_(name);
window.localStorage.removeItem('piskel.' + name);
};
ns.LocalStorageService.prototype.saveKeys_ = function(keys) {
window.localStorage.setItem('piskel.keys', JSON.stringify(keys));
};
ns.LocalStorageService.prototype.removeFromKeys_ = function(name) {
var keys = this.getKeys();
var otherKeys = keys.filter(function (key) {
return key.name !== name;
});
this.saveKeys_(otherKeys);
};
ns.LocalStorageService.prototype.getKey_ = function(name) {
var matches = this.getKeys().filter(function (key) {
return key.name === name;
});
if (matches.length > 0) {
return matches[0];
} else {
return null;
}
};
ns.LocalStorageService.prototype.addToKeys_ = function(name, description, date) {
var keys = this.getKeys();
keys.push({
name : name,
description : description,
date : date
});
this.saveKeys_(keys);
};
ns.LocalStorageService.prototype.getPiskel = function(name) {
return window.localStorage.getItem('piskel.' + name);
};
ns.LocalStorageService.prototype.getKeys = function(name) {
var keysString = window.localStorage.getItem('piskel.keys');
return JSON.parse(keysString) || [];
};
})();

View File

@ -1,64 +0,0 @@
(function () {
var ns = $.namespace('pskl.service');
ns.SavedStatusService = function (piskelController) {
this.piskelController_ = piskelController;
};
ns.SavedStatusService.prototype.init = function () {
$.subscribe(Events.TOOL_RELEASED, this.onToolReleased.bind(this));
$.subscribe(Events.PISKEL_RESET, this.onPiskelReset.bind(this));
$.subscribe(Events.PISKEL_SAVED, this.onPiskelSaved.bind(this));
window.addEventListener("beforeunload", this.onBeforeUnload.bind(this));
};
ns.SavedStatusService.prototype.onPiskelReset = function () {
var piskel = this.piskelController_.piskel;
// A first PISKEL_RESET is triggered during the load of a new Piskel, it should be ignored
// putting a firstResetDone flag as a nasty workaround for this
if (piskel.firstResetDone_) {
this.updateDirtyStatus(true);
} else {
piskel.firstResetDone_ = true;
}
};
ns.SavedStatusService.prototype.onToolReleased = function () {
this.updateDirtyStatus(true);
};
ns.SavedStatusService.prototype.onPiskelSaved = function () {
this.updateDirtyStatus(false);
};
ns.SavedStatusService.prototype.updateDirtyStatus = function (status) {
var piskel = this.piskelController_.piskel;
if (piskel.isDirty_ !== status) {
// Redraw piskel name only if dirty status actually changed
piskel.isDirty_ = status;
this.updatePiskelName();
}
};
ns.SavedStatusService.prototype.updatePiskelName = function () {
var piskel = this.piskelController_.piskel;
var name = piskel.getDescriptor().name;
if (piskel.isDirty_) {
$('.piskel-name').html(name + ' *');
} else {
$('.piskel-name').html(name);
}
};
ns.SavedStatusService.prototype.onBeforeUnload = function (evt) {
var piskel = this.piskelController_.piskel;
if (piskel.isDirty_) {
var confirmationMessage = "Your Piskel seems to have unsaved changes";
(evt || window.event).returnValue = confirmationMessage;
return confirmationMessage;
}
};
})();

View File

@ -1,121 +0,0 @@
(function () {
var ns = $.namespace('pskl.service.keyboard');
ns.CheatsheetService = function () {
this.isDisplayed_ = false;
};
ns.CheatsheetService.prototype.init = function () {
this.cheatsheetEl_ = document.getElementById('cheatsheet-wrapper');
if (!this.cheatsheetEl_) {
throw 'cheatsheetEl_ DOM element could not be retrieved';
}
this.initMarkup_();
pskl.app.shortcutService.addShortcut('shift+?', this.toggleCheatsheet_.bind(this));
pskl.app.shortcutService.addShortcut('?', this.toggleCheatsheet_.bind(this));
var link = $('.cheatsheet-link');
link.click(this.toggleCheatsheet_.bind(this));
$.subscribe(Events.TOGGLE_HELP, this.toggleCheatsheet_.bind(this));
$.subscribe(Events.ESCAPE, this.onEscape_.bind(this));
};
ns.CheatsheetService.prototype.toggleCheatsheet_ = function () {
if (this.isDisplayed_) {
this.hideCheatsheet_();
} else {
this.showCheatsheet_();
}
};
ns.CheatsheetService.prototype.onEscape_ = function () {
if (this.isDisplayed_) {
this.hideCheatsheet_();
}
};
ns.CheatsheetService.prototype.showCheatsheet_ = function () {
pskl.app.shortcutService.addShortcut('ESC', this.hideCheatsheet_.bind(this));
this.cheatsheetEl_.style.display = 'block';
this.isDisplayed_ = true;
};
ns.CheatsheetService.prototype.hideCheatsheet_ = function () {
pskl.app.shortcutService.removeShortcut('ESC');
this.cheatsheetEl_.style.display = 'none';
this.isDisplayed_ = false;
};
ns.CheatsheetService.prototype.initMarkup_ = function () {
this.initMarkupForTools_();
this.initMarkupForMisc_();
this.initMarkupForSelection_();
};
ns.CheatsheetService.prototype.toDescriptor_ = function (shortcut, description, icon) {
return {
'shortcut' : shortcut,
'description' : description,
'icon' : icon
};
};
ns.CheatsheetService.prototype.getDomFromDescriptor_ = function (descriptor) {
var shortcutTemplate = pskl.utils.Template.get('cheatsheet-shortcut-template');
var markup = pskl.utils.Template.replace(shortcutTemplate, {
shortcutIcon : descriptor.icon,
shortcutDescription : descriptor.description,
shortcutKey : descriptor.shortcut
});
return pskl.utils.Template.createFromHTML(markup);
};
ns.CheatsheetService.prototype.initMarkupAbstract_ = function (descriptors, containerSelector) {
var container = $(containerSelector, this.cheatsheetEl_).get(0);
for (var i = 0 ; i < descriptors.length ; i++) {
var descriptor = descriptors[i];
var shortcutEl = this.getDomFromDescriptor_(descriptor);
container.appendChild(shortcutEl);
}
};
ns.CheatsheetService.prototype.initMarkupForTools_ = function () {
var descriptors = pskl.app.toolController.tools.map(function (tool) {
return this.toDescriptor_(tool.shortcut, tool.instance.helpText, 'tool-icon ' + tool.instance.toolId);
}.bind(this));
this.initMarkupAbstract_(descriptors, '.cheatsheet-tool-shortcuts');
};
ns.CheatsheetService.prototype.initMarkupForMisc_ = function () {
var descriptors = [
this.toDescriptor_('X', 'Swap primary/secondary colors'),
this.toDescriptor_('D', 'Reset default colors'),
this.toDescriptor_('ctrl + Z', 'Undo'),
this.toDescriptor_('ctrl + Y', 'Redo'),
this.toDescriptor_('&#65514;', 'Select previous frame'), /* ASCII for up-arrow */
this.toDescriptor_('&#65516;', 'Select next frame'), /* ASCII for down-arrow */
this.toDescriptor_('N', 'Create new frame'),
this.toDescriptor_('shift + N', 'Duplicate selected frame'),
this.toDescriptor_('shift + ?', 'Open/Close this popup'),
this.toDescriptor_('alt + P', 'Open the Palette Manager')
];
this.initMarkupAbstract_(descriptors, '.cheatsheet-misc-shortcuts');
};
ns.CheatsheetService.prototype.initMarkupForSelection_ = function () {
var descriptors = [
this.toDescriptor_('ctrl + X', 'Cut selection'),
this.toDescriptor_('ctrl + C', 'Copy selection'),
this.toDescriptor_('ctrl + V', 'Paste selection'),
this.toDescriptor_('del', 'Delete selection')
];
this.initMarkupAbstract_(descriptors, '.cheatsheet-selection-shortcuts');
};
})();

View File

@ -1,25 +0,0 @@
(function () {
var specialKeys = {
191 : "?",
27 : "esc",
38 : "up",
40 : "down",
46 : "del"
};
var ns = $.namespace('pskl.service.keyboard');
ns.KeycodeTranslator= {
toChar : function (keycode) {
if (keycode >= 48 && keycode <= 57) {
// key is 0-9
return (keycode - 48) + "";
} else if (keycode >= 65 && keycode <= 90) {
// key is a-z, use base 36 to get the string representation
return (keycode - 65 + 10).toString(36);
} else {
return specialKeys[keycode];
}
}
};
})();

View File

@ -1,108 +0,0 @@
(function () {
var ns = $.namespace('pskl.service.keyboard');
ns.ShortcutService = function () {
this.shortcuts_ = {};
};
/**
* @public
*/
ns.ShortcutService.prototype.init = function() {
$(document.body).keydown($.proxy(this.onKeyUp_, this));
};
ns.ShortcutService.prototype.addShortcut = function (rawKey, callback) {
var parsedKey = this.parseKey_(rawKey.toLowerCase());
var key = parsedKey.key,
meta = parsedKey.meta;
this.shortcuts_[key] = this.shortcuts_[key] || {};
if (this.shortcuts_[key][meta]) {
var keyStr = (meta !== 'normal' ? meta + ' + ' : '') + key;
console.error('[ShortcutService] >>> Shortcut [' + keyStr + '] already registered');
} else {
this.shortcuts_[key][meta] = callback;
}
};
ns.ShortcutService.prototype.removeShortcut = function (rawKey) {
var parsedKey = this.parseKey_(rawKey.toLowerCase());
var key = parsedKey.key,
meta = parsedKey.meta;
this.shortcuts_[key] = this.shortcuts_[key] || {};
this.shortcuts_[key][meta] = null;
};
ns.ShortcutService.prototype.parseKey_ = function (key) {
var meta = 'normal';
if (key.indexOf('ctrl+') === 0) {
meta = 'ctrl';
key = key.replace('ctrl+', '');
} else if (key.indexOf('shift+') === 0) {
meta = 'shift';
key = key.replace('shift+', '');
} else if (key.indexOf('alt+') === 0) {
meta = 'alt';
key = key.replace('alt+', '');
}
return {meta : meta, key : key};
};
/**
* @private
*/
ns.ShortcutService.prototype.onKeyUp_ = function(evt) {
if (!this.isInInput_(evt)) {
// jquery names FTW ...
var keycode = evt.which;
var targetTagName = evt.target.nodeName.toUpperCase();
var charkey = pskl.service.keyboard.KeycodeTranslator.toChar(keycode);
var keyShortcuts = this.shortcuts_[charkey];
if(keyShortcuts) {
var cb;
if (this.isCtrlKeyPressed_(evt)) {
cb = keyShortcuts.ctrl;
} else if (this.isShiftKeyPressed_(evt)) {
cb = keyShortcuts.shift;
} else if (this.isAltKeyPressed_(evt)) {
cb = keyShortcuts.alt;
} else {
cb = keyShortcuts.normal;
}
if(cb) {
cb(charkey);
evt.preventDefault();
}
}
}
};
ns.ShortcutService.prototype.isInInput_ = function (evt) {
var targetTagName = evt.target.nodeName.toUpperCase();
return targetTagName === 'INPUT' || targetTagName === 'TEXTAREA';
};
ns.ShortcutService.prototype.isCtrlKeyPressed_ = function (evt) {
return this.isMac_() ? evt.metaKey : evt.ctrlKey;
};
ns.ShortcutService.prototype.isShiftKeyPressed_ = function (evt) {
return evt.shiftKey;
};
ns.ShortcutService.prototype.isAltKeyPressed_ = function (evt) {
return evt.altKey;
};
ns.ShortcutService.prototype.isMac_ = function () {
return navigator.appVersion.indexOf("Mac") != -1;
};
})();

View File

@ -1,49 +0,0 @@
(function () {
var ns = $.namespace("pskl");
ns.CanvasUtils = {
createCanvas : function (width, height, classList) {
var canvas = document.createElement("canvas");
canvas.setAttribute("width", width);
canvas.setAttribute("height", height);
if (typeof classList == "string") {
classList = [classList];
}
if (Array.isArray(classList)) {
for (var i = 0 ; i < classList.length ; i++) {
canvas.classList.add(classList[i]);
}
}
return canvas;
},
/**
* By default, all scaling operations on a Canvas 2D Context are performed using antialiasing.
* Resizing a 32x32 image to 320x320 will lead to a blurry output.
* On Chrome, FF and IE>=11, this can be disabled by setting a property on the Canvas 2D Context.
* In this case the browser will use a nearest-neighbor scaling.
* @param {Canvas} canvas
*/
disableImageSmoothing : function (canvas) {
var context = canvas.getContext('2d');
context.imageSmoothingEnabled = false;
context.mozImageSmoothingEnabled = false;
context.oImageSmoothingEnabled = false;
context.webkitImageSmoothingEnabled = false;
context.msImageSmoothingEnabled = false;
},
clear : function (canvas) {
if (canvas) {
canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height);
}
},
getImageDataFromCanvas : function (canvas) {
var sourceContext = canvas.getContext('2d');
return sourceContext.getImageData(0, 0, canvas.width, canvas.height).data;
}
};
})();

View File

@ -1,29 +0,0 @@
(function () {
var ns = $.namespace('pskl.utils');
ns.Dom = {
/**
* Check if a given HTML element is nested inside another
* @param {HTMLElement} node Element to test
* @param {HTMLElement} parent Potential Ancestor for node
* @param {Boolean} excludeParent set to true if the parent should be excluded from potential matches
* @return {Boolean} true if parent was found amongst the parentNode chain of node
*/
isParent : function (node, parent, excludeParent) {
if (node && parent) {
if (excludeParent) {
node = node.parentNode;
}
while (node) {
if (node === parent) {
return true;
}
node = node.parentNode;
}
}
return false;
}
};
})();

View File

@ -1,13 +0,0 @@
(function () {
var ns = $.namespace('pskl.utils');
ns.FileUtils = {
readFile : function (file, callback) {
var reader = new FileReader();
reader.onload = function(event){
callback(event.target.result);
};
reader.readAsDataURL(file);
}
};
})();

View File

@ -1,156 +0,0 @@
(function () {
var ns = $.namespace('pskl.utils');
var colorCache = {};
ns.FrameUtils = {
merge : function (frames) {
var merged = null;
if (frames.length) {
merged = frames[0].clone();
var w = merged.getWidth(), h = merged.getHeight();
for (var i = 1 ; i < frames.length ; i++) {
pskl.utils.FrameUtils.mergeFrames_(merged, frames[i]);
}
}
return merged;
},
mergeFrames_ : function (frameA, frameB) {
frameB.forEachPixel(function (p, col, row) {
if (p != Constants.TRANSPARENT_COLOR) {
frameA.setPixel(col, row, p);
}
});
},
/**
* Alpha compositing using porter duff algorithm :
* http://en.wikipedia.org/wiki/Alpha_compositing
* http://keithp.com/~keithp/porterduff/p253-porter.pdf
* @param {String} strColor1 color over
* @param {String} strColor2 color under
* @return {String} the composite color
*/
mergePixels : function (strColor1, strColor2, globalOpacity1) {
var col1 = pskl.utils.FrameUtils.toRgba(strColor1);
var col2 = pskl.utils.FrameUtils.toRgba(strColor2);
if (typeof globalOpacity1 == 'number') {
col1 = JSON.parse(JSON.stringify(col1));
col1.a = globalOpacity1 * col1.a;
}
var a = col1.a + col2.a * (1 - col1.a);
var r = ((col1.r * col1.a + col2.r * col2.a * (1 - col1.a)) / a)|0;
var g = ((col1.g * col1.a + col2.g * col2.a * (1 - col1.a)) / a)|0;
var b = ((col1.b * col1.a + col2.b * col2.a * (1 - col1.a)) / a)|0;
return 'rgba('+r+','+g+','+b+','+a+')';
},
/**
* Convert a color defined as a string (hex, rgba, rgb, 'TRANSPARENT') to an Object with r,g,b,a properties.
* r, g and b are integers between 0 and 255, a is a float between 0 and 1
* @param {String} c color as a string
* @return {Object} {r:Number,g:Number,b:Number,a:Number}
*/
toRgba : function (c) {
if (colorCache[c]) {
return colorCache[c];
}
var color, matches;
if (c === 'TRANSPARENT') {
color = {
r : 0,
g : 0,
b : 0,
a : 0
};
} else if (c.indexOf('rgba(') != -1) {
matches = /rgba\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(1|0\.\d+)\s*\)/.exec(c);
color = {
r : parseInt(matches[1],10),
g : parseInt(matches[2],10),
b : parseInt(matches[3],10),
a : parseFloat(matches[4])
};
} else if (c.indexOf('rgb(') != -1) {
matches = /rgb\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/.exec(c);
color = {
r : parseInt(matches[1],10),
g : parseInt(matches[2],10),
b : parseInt(matches[3],10),
a : 1
};
} else {
matches = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(c);
color = {
r : parseInt(matches[1], 16),
g : parseInt(matches[2], 16),
b : parseInt(matches[3], 16),
a : 1
};
}
colorCache[c] = color;
return color;
},
/*
* Create a pskl.model.Frame from an Image object.
* Transparent pixels will either be converted to completely opaque or completely transparent pixels.
* @param {Image} image source image
* @return {pskl.model.Frame} corresponding frame
*/
createFromImage : function (image) {
var w = image.width,
h = image.height;
var canvas = pskl.CanvasUtils.createCanvas(w, h);
var context = canvas.getContext('2d');
context.drawImage(image, 0,0,w,h,0,0,w,h);
var imgData = context.getImageData(0,0,w,h).data;
return pskl.utils.FrameUtils.createFromImageData(imgData, w, h);
},
createFromImageData : function (imageData, width, height) {
// Draw the zoomed-up pixels to a different canvas context
var grid = [];
for (var x = 0 ; x < width ; x++){
grid[x] = [];
for (var y = 0 ; y < height ; y++){
// Find the starting index in the one-dimensional image data
var i = (y * width + x)*4;
var r = imageData[i ];
var g = imageData[i+1];
var b = imageData[i+2];
var a = imageData[i+3];
if (a < 125) {
grid[x][y] = Constants.TRANSPARENT_COLOR;
} else {
grid[x][y] = pskl.utils.FrameUtils.rgbToHex(r,g,b);
}
}
}
return pskl.model.Frame.fromPixelGrid(grid);
},
/**
* Convert a rgb(Number, Number, Number) color to hexadecimal representation
* @param {Number} r red value, between 0 and 255
* @param {Number} g green value, between 0 and 255
* @param {Number} b blue value, between 0 and 255
* @return {String} hex representation of the color '#ABCDEF'
*/
rgbToHex : function (r, g, b) {
return "#" + this.componentToHex(r) + this.componentToHex(g) + this.componentToHex(b);
},
/**
* Convert a color component (as a Number between 0 and 255) to its string hexa representation
* @param {Number} c component value, between 0 and 255
* @return {String} eg. '0A'
*/
componentToHex : function (c) {
var hex = c.toString(16);
return hex.length == 1 ? "0" + hex : hex;
}
};
})();

View File

@ -1,83 +0,0 @@
(function () {
var ns = $.namespace('pskl.utils');
ns.ImageResizer = {
resize : function (image, targetWidth, targetHeight, smoothingEnabled) {
var canvas = pskl.CanvasUtils.createCanvas(targetWidth, targetHeight);
var context = canvas.getContext('2d');
context.save();
if (!smoothingEnabled) {
pskl.CanvasUtils.disableImageSmoothing(canvas);
}
context.translate(canvas.width / 2, canvas.height / 2);
context.scale(targetWidth / image.width, targetHeight / image.height);
context.drawImage(image, -image.width / 2, -image.height / 2);
context.restore();
return canvas;
},
/**
* Manual implementation of resize using a nearest neighbour algorithm
* It is slower than relying on the native 'disabledImageSmoothing' available on CanvasRenderingContext2d.
* But it can be useful if :
* - IE < 11 (doesn't support msDisableImageSmoothing)
* - need to display a gap between pixel
*
* @param {Canvas2d} source original image to be resized, as a 2d canvas
* @param {Number} zoom ratio between desired dim / source dim
* @param {Number} margin gap to be displayed between pixels
* @param {String} color or the margin (will be transparent if not provided)
* @return {Canvas2d} the resized canvas
*/
resizeNearestNeighbour : function (source, zoom, margin, marginColor) {
margin = margin || 0;
var canvas = pskl.CanvasUtils.createCanvas(zoom*source.width, zoom*source.height);
var context = canvas.getContext('2d');
var imgData = pskl.CanvasUtils.getImageDataFromCanvas(source);
var yRanges = {},
xOffset = 0,
yOffset = 0,
xRange,
yRange;
// Draw the zoomed-up pixels to a different canvas context
for (var x = 0; x < source.width; x++) {
// Calculate X Range
xRange = Math.floor((x + 1) * zoom) - xOffset;
for (var y = 0; y < source.height; y++) {
// Calculate Y Range
if (!yRanges[y + ""]) {
// Cache Y Range
yRanges[y + ""] = Math.floor((y + 1) * zoom) - yOffset;
}
yRange = yRanges[y + ""];
var i = (y * source.width + x) * 4;
var r = imgData[i];
var g = imgData[i + 1];
var b = imgData[i + 2];
var a = imgData[i + 3];
context.fillStyle = "rgba(" + r + "," + g + "," + b + "," + (a / 255) + ")";
context.fillRect(xOffset, yOffset, xRange-margin, yRange-margin);
if (margin && marginColor) {
context.fillStyle = marginColor;
context.fillRect(xOffset + xRange - margin, yOffset, margin, yRange);
context.fillRect(xOffset, yOffset + yRange - margin, xRange, margin);
}
yOffset += yRange;
}
yOffset = 0;
xOffset += xRange;
}
return canvas;
}
};
})();

Some files were not shown because too many files have changed in this diff Show More