mirror of
https://github.com/piskelapp/piskel.git
synced 2023-08-10 21:12:52 +03:00
update for darken/lighten
This commit is contained in:
parent
db9e832984
commit
e9a5e27266
10
build/piskel-packaged-min.js
vendored
10
build/piskel-packaged-min.js
vendored
File diff suppressed because one or more lines are too long
8
css/bootstrap/bootstrap-tooltip-custom.css
vendored
8
css/bootstrap/bootstrap-tooltip-custom.css
vendored
@ -1,8 +0,0 @@
|
||||
.tooltip.in {
|
||||
opacity: 0.95;
|
||||
filter: alpha(opacity=95);
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
line-height: 20px;
|
||||
}
|
112
css/bootstrap/bootstrap.css
vendored
112
css/bootstrap/bootstrap.css
vendored
@ -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;
|
||||
}
|
@ -1 +0,0 @@
|
||||
Bootstrap custom build containing only the tooltip component
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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 {
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
316
css/settings.css
316
css/settings.css
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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=);
|
||||
}
|
247
css/style.css
247
css/style.css
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
226
css/tools.css
226
css/tools.css
@ -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
BIN
img/tools/lighten.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
@ -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>
|
||||
|
||||
|
@ -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';}
|
||||
};
|
51
js/Events.js
51
js/Events.js
@ -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
236
js/app.js
@ -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);
|
||||
}
|
||||
};
|
||||
})();
|
@ -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);
|
||||
};
|
||||
})();
|
@ -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);
|
||||
};
|
||||
})();
|
@ -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();
|
||||
}
|
||||
};
|
||||
})();
|
@ -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;
|
||||
};
|
||||
})();
|
@ -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();
|
||||
}
|
||||
};
|
||||
})();
|
@ -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);
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
|
@ -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) || [];
|
||||
};
|
||||
})();
|
@ -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));
|
||||
};
|
||||
})();
|
@ -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;
|
||||
};
|
||||
})();
|
@ -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));
|
||||
}
|
||||
};
|
||||
})();
|
@ -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;
|
||||
};
|
||||
|
||||
})();
|
@ -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')];
|
||||
};
|
||||
|
||||
})();
|
@ -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');
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
@ -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;
|
||||
};
|
||||
})();
|
@ -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;
|
||||
};
|
||||
|
||||
})();
|
@ -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;
|
||||
};
|
||||
|
||||
})();
|
@ -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;
|
||||
};
|
||||
})();
|
@ -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);
|
||||
};
|
||||
})();
|
@ -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);
|
||||
};
|
||||
})();
|
@ -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;
|
||||
};
|
||||
|
||||
})();
|
@ -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;
|
||||
};
|
||||
})();
|
@ -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;
|
||||
};
|
||||
})();
|
@ -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]);
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
@ -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);
|
||||
};
|
||||
})();
|
@ -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);
|
||||
};
|
||||
})();
|
@ -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);
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
})();
|
@ -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;
|
||||
};
|
||||
})();
|
@ -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();
|
||||
};
|
||||
})();
|
@ -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;
|
||||
};
|
||||
})();
|
@ -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);
|
||||
};
|
||||
})();
|
@ -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);
|
||||
};
|
||||
|
||||
})();
|
@ -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
BIN
js/lib/.DS_Store
vendored
Binary file not shown.
275
js/lib/bootstrap/bootstrap.js
vendored
275
js/lib/bootstrap/bootstrap.js
vendored
@ -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);
|
@ -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
9227
js/lib/jquery-1.8.0.js
vendored
File diff suppressed because it is too large
Load Diff
2252
js/lib/jquery-ui-1.10.3.custom.js
vendored
2252
js/lib/jquery-ui-1.10.3.custom.js
vendored
File diff suppressed because it is too large
Load Diff
@ -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
@ -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();
|
||||
};
|
||||
})();
|
@ -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;
|
||||
};
|
||||
})();
|
@ -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);
|
||||
};
|
||||
|
||||
})();
|
@ -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
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
@ -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;
|
||||
})();
|
@ -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);
|
||||
};
|
||||
})();
|
@ -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';
|
||||
}
|
||||
};
|
||||
})();
|
@ -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;
|
||||
};
|
||||
})();
|
@ -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);
|
||||
};
|
||||
|
||||
})();
|
@ -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);
|
||||
})();
|
@ -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);
|
||||
}
|
||||
};
|
||||
})();
|
@ -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();
|
||||
};
|
||||
})();
|
@ -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);
|
||||
};
|
||||
})();
|
@ -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;
|
||||
};
|
||||
})();
|
@ -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);
|
||||
})();
|
@ -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";
|
||||
}
|
||||
};
|
||||
})();
|
@ -1,9 +0,0 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.selection");
|
||||
|
||||
ns.ShapeSelection = function (pixels) {
|
||||
this.pixels = pixels;
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.ShapeSelection, ns.BaseSelection);
|
||||
})();
|
@ -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;
|
||||
};
|
||||
})();
|
@ -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);
|
||||
};
|
||||
})();
|
@ -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);
|
||||
};
|
||||
|
||||
})();
|
@ -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);
|
||||
};
|
||||
})();
|
@ -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) || [];
|
||||
};
|
||||
|
||||
})();
|
@ -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;
|
||||
}
|
||||
};
|
||||
})();
|
@ -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_('↑', 'Select previous frame'), /* ASCII for up-arrow */
|
||||
this.toDescriptor_('↓', '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');
|
||||
};
|
||||
|
||||
})();
|
@ -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];
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
@ -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;
|
||||
};
|
||||
})();
|
@ -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;
|
||||
}
|
||||
};
|
||||
})();
|
@ -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;
|
||||
}
|
||||
};
|
||||
})();
|
@ -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);
|
||||
}
|
||||
};
|
||||
})();
|
@ -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;
|
||||
}
|
||||
};
|
||||
})();
|
@ -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
Loading…
Reference in New Issue
Block a user