Merge branch 'dev'
@ -44,6 +44,7 @@ option(ENABLE_UPDATER "Enable automatic check for updates" on)
|
||||
option(ENABLE_WEBSERVER "Enable support to run a webserver (for HTML5 gamedev)" off)
|
||||
option(ENABLE_TRIAL_MODE "Compile the trial version" off)
|
||||
option(FULLSCREEN_PLATFORM "Enable fullscreen by default" off)
|
||||
set(CUSTOM_WEBSITE_URL "" CACHE STRING "Enable custom local webserver to check updates")
|
||||
|
||||
######################################################################
|
||||
# Profile build type
|
||||
|
16
TODO.md
@ -1,9 +1,15 @@
|
||||
# Before release
|
||||
# Next release
|
||||
|
||||
* timeline: move a layer to the same place -> crash
|
||||
* timeline: select all layers and remove -> crash
|
||||
* timeline: move cel with right click -> crash
|
||||
* fix animation playback (the duration is not used correctly)
|
||||
* ColorSelector: change color type when a tab is pressed
|
||||
* canvas dialog should show width and height and expansion point
|
||||
* double click or right click a range outline in timeline should open popups or properties
|
||||
|
||||
# Hard to reproduce bugs
|
||||
|
||||
* does lock alpha work correctly?
|
||||
* does onscrollchange notification calls onscrollchange notification?
|
||||
* random clicks on toolbar crashes the program
|
||||
* click Desktop item in file selector crashes the program
|
||||
|
||||
# Tasks
|
||||
|
||||
|
25
data/gui.xml
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- ASE menus, tools and keyboard shortcuts -->
|
||||
<gui version="0.9.6-dev">
|
||||
<gui version="1.0.0-dev">
|
||||
<!-- Keyboard shortcuts -->
|
||||
<keyboard>
|
||||
|
||||
@ -18,7 +18,9 @@
|
||||
<key command="AdvancedMode" shortcut="F11" />
|
||||
<key command="DeveloperConsole" shortcut="F12" />
|
||||
<key command="Exit" shortcut="Alt+F4" />
|
||||
<key command="Cancel" shortcut="Esc" />
|
||||
<key command="Cancel" shortcut="Esc">
|
||||
<param name="type" value="all" />
|
||||
</key>
|
||||
<!-- Edit -->
|
||||
<key command="Undo" shortcut="Ctrl+Z" /> <key command="Undo" shortcut="Ctrl+U" />
|
||||
<key command="Redo" shortcut="Ctrl+Y" />
|
||||
@ -74,6 +76,7 @@
|
||||
<key command="Preview" shortcut="F8" />
|
||||
<key command="ShowGrid" shortcut="Shift+G" />
|
||||
<key command="SnapToGrid" shortcut="Shift+S" />
|
||||
<key command="ShowOnionSkin" shortcut="F3" />
|
||||
<key command="Timeline" shortcut="Tab">
|
||||
<param name="switch" value="true" />
|
||||
</key>
|
||||
@ -373,6 +376,8 @@
|
||||
<item command="SnapToGrid" text="&Snap to Grid" />
|
||||
<item command="GridSettings" text="Gri&d Settings" />
|
||||
<separator />
|
||||
<item command="ShowOnionSkin" text="Show &Onion Skin" />
|
||||
<separator />
|
||||
<item command="Timeline" text="&Timeline">
|
||||
<param name="switch" value="true" />
|
||||
</item>
|
||||
@ -387,21 +392,21 @@
|
||||
</item>
|
||||
<separator />
|
||||
<item command="Launch" text="Quick &Reference">
|
||||
<param name="type" value="docs" />
|
||||
<param name="path" value="http://www.aseprite.org/quickref/" />
|
||||
<param name="type" value="url" />
|
||||
<param name="path" value="/quickref/" />
|
||||
</item>
|
||||
<item command="Launch" text="Documentation">
|
||||
<param name="type" value="url" />
|
||||
<param name="path" value="http://www.aseprite.org/docs/" />
|
||||
<param name="path" value="/docs/" />
|
||||
</item>
|
||||
<item command="Launch" text="Tutorial">
|
||||
<param name="type" value="url" />
|
||||
<param name="path" value="http://www.aseprite.org/tutorial/" />
|
||||
<param name="path" value="/tutorial/" />
|
||||
</item>
|
||||
<separator />
|
||||
<item command="Launch" text="Release Notes">
|
||||
<param name="type" value="url" />
|
||||
<param name="path" value="http://www.aseprite.org/release-notes/" />
|
||||
<param name="path" value="/release-notes/" />
|
||||
</item>
|
||||
<item command="Launch" text="Twitter">
|
||||
<param name="type" value="url" />
|
||||
@ -410,7 +415,7 @@
|
||||
<separator />
|
||||
<item command="Launch" text="&Donate">
|
||||
<param name="type" value="url" />
|
||||
<param name="path" value="http://www.aseprite.org/donate/" />
|
||||
<param name="path" value="/donate/" />
|
||||
</item>
|
||||
<item command="About" text="&About" />
|
||||
</menu>
|
||||
@ -454,6 +459,10 @@
|
||||
<menu id="cel_movement_popup">
|
||||
<item command="MoveCel" text="&Move" />
|
||||
<item command="CopyCel" text="&Copy" />
|
||||
<separator />
|
||||
<item command="Cancel" text="Cancel">
|
||||
<param name="type" value="noop" />
|
||||
</item>
|
||||
</menu>
|
||||
</menus>
|
||||
|
||||
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 925 B After Width: | Height: | Size: 191 B |
Before Width: | Height: | Size: 534 B After Width: | Height: | Size: 255 B |
Before Width: | Height: | Size: 713 B After Width: | Height: | Size: 308 B |
Before Width: | Height: | Size: 649 B After Width: | Height: | Size: 372 B |
18
data/palettes/apple-ii.gpl
Normal file
@ -0,0 +1,18 @@
|
||||
GIMP Palette
|
||||
#
|
||||
0 0 0 Untitled
|
||||
108 41 64 Untitled
|
||||
64 53 120 Untitled
|
||||
217 60 240 Untitled
|
||||
19 87 64 Untitled
|
||||
128 128 128 Untitled
|
||||
38 151 240 Untitled
|
||||
191 180 248 Untitled
|
||||
64 75 7 Untitled
|
||||
217 104 15 Untitled
|
||||
128 128 128 Untitled
|
||||
236 168 191 Untitled
|
||||
38 195 15 Untitled
|
||||
191 202 135 Untitled
|
||||
147 214 191 Untitled
|
||||
255 255 255 Untitled
|
258
data/palettes/atari2600-ntsc.gpl
Normal file
@ -0,0 +1,258 @@
|
||||
GIMP Palette
|
||||
#
|
||||
0 0 0 Untitled
|
||||
68 68 0 Untitled
|
||||
112 40 0 Untitled
|
||||
132 24 0 Untitled
|
||||
136 0 0 Untitled
|
||||
120 0 92 Untitled
|
||||
72 0 120 Untitled
|
||||
20 0 132 Untitled
|
||||
0 0 136 Untitled
|
||||
0 24 124 Untitled
|
||||
0 44 92 Untitled
|
||||
0 64 44 Untitled
|
||||
0 60 0 Untitled
|
||||
20 56 0 Untitled
|
||||
44 48 0 Untitled
|
||||
68 40 0 Untitled
|
||||
64 64 64 Untitled
|
||||
100 100 16 Untitled
|
||||
132 68 20 Untitled
|
||||
152 52 24 Untitled
|
||||
156 32 32 Untitled
|
||||
140 32 116 Untitled
|
||||
96 32 144 Untitled
|
||||
48 32 152 Untitled
|
||||
28 32 156 Untitled
|
||||
28 56 144 Untitled
|
||||
28 76 120 Untitled
|
||||
28 92 72 Untitled
|
||||
32 92 32 Untitled
|
||||
52 92 28 Untitled
|
||||
76 80 28 Untitled
|
||||
100 72 24 Untitled
|
||||
108 108 108 Untitled
|
||||
132 132 36 Untitled
|
||||
152 92 40 Untitled
|
||||
172 80 48 Untitled
|
||||
176 60 60 Untitled
|
||||
160 60 136 Untitled
|
||||
120 60 164 Untitled
|
||||
76 60 172 Untitled
|
||||
56 64 176 Untitled
|
||||
56 84 168 Untitled
|
||||
56 104 144 Untitled
|
||||
56 124 100 Untitled
|
||||
64 124 64 Untitled
|
||||
80 124 56 Untitled
|
||||
104 112 52 Untitled
|
||||
132 104 48 Untitled
|
||||
144 144 144 Untitled
|
||||
160 160 52 Untitled
|
||||
172 120 60 Untitled
|
||||
192 104 72 Untitled
|
||||
192 88 88 Untitled
|
||||
176 88 156 Untitled
|
||||
140 88 184 Untitled
|
||||
104 88 192 Untitled
|
||||
80 92 192 Untitled
|
||||
80 112 188 Untitled
|
||||
80 132 172 Untitled
|
||||
80 156 128 Untitled
|
||||
92 156 92 Untitled
|
||||
108 152 80 Untitled
|
||||
132 140 76 Untitled
|
||||
160 132 68 Untitled
|
||||
176 176 176 Untitled
|
||||
184 184 64 Untitled
|
||||
188 140 76 Untitled
|
||||
208 128 92 Untitled
|
||||
208 112 112 Untitled
|
||||
192 112 176 Untitled
|
||||
160 112 204 Untitled
|
||||
124 112 208 Untitled
|
||||
104 116 208 Untitled
|
||||
104 136 204 Untitled
|
||||
104 156 192 Untitled
|
||||
104 180 148 Untitled
|
||||
116 180 116 Untitled
|
||||
132 180 104 Untitled
|
||||
156 168 100 Untitled
|
||||
184 156 88 Untitled
|
||||
200 200 200 Untitled
|
||||
208 208 80 Untitled
|
||||
204 160 92 Untitled
|
||||
224 148 112 Untitled
|
||||
224 136 136 Untitled
|
||||
208 132 192 Untitled
|
||||
180 132 220 Untitled
|
||||
148 136 224 Untitled
|
||||
124 140 224 Untitled
|
||||
124 156 220 Untitled
|
||||
124 180 212 Untitled
|
||||
124 208 172 Untitled
|
||||
140 208 140 Untitled
|
||||
156 204 124 Untitled
|
||||
180 192 120 Untitled
|
||||
208 180 108 Untitled
|
||||
220 220 220 Untitled
|
||||
232 232 92 Untitled
|
||||
220 180 104 Untitled
|
||||
236 168 128 Untitled
|
||||
236 160 160 Untitled
|
||||
220 156 208 Untitled
|
||||
196 156 236 Untitled
|
||||
168 160 236 Untitled
|
||||
144 164 236 Untitled
|
||||
144 180 236 Untitled
|
||||
144 204 232 Untitled
|
||||
144 228 192 Untitled
|
||||
164 228 164 Untitled
|
||||
180 228 144 Untitled
|
||||
204 212 136 Untitled
|
||||
232 204 124 Untitled
|
||||
236 236 236 Untitled
|
||||
252 252 104 Untitled
|
||||
236 200 120 Untitled
|
||||
252 188 148 Untitled
|
||||
252 180 180 Untitled
|
||||
236 176 224 Untitled
|
||||
212 176 252 Untitled
|
||||
188 180 252 Untitled
|
||||
164 184 252 Untitled
|
||||
164 200 252 Untitled
|
||||
164 224 252 Untitled
|
||||
164 252 212 Untitled
|
||||
184 252 184 Untitled
|
||||
200 252 164 Untitled
|
||||
224 236 156 Untitled
|
||||
252 224 140 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
255 255 255 Untitled
|
130
data/palettes/atari2600-pal.gpl
Normal file
@ -0,0 +1,130 @@
|
||||
GIMP Palette
|
||||
#
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
128 88 0 Untitled
|
||||
68 92 0 Untitled
|
||||
112 52 0 Untitled
|
||||
0 100 20 Untitled
|
||||
112 0 20 Untitled
|
||||
0 92 92 Untitled
|
||||
112 0 92 Untitled
|
||||
0 60 112 Untitled
|
||||
88 0 112 Untitled
|
||||
0 32 112 Untitled
|
||||
60 0 128 Untitled
|
||||
0 0 136 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
64 64 64 Untitled
|
||||
64 64 64 Untitled
|
||||
148 112 32 Untitled
|
||||
92 120 32 Untitled
|
||||
136 80 32 Untitled
|
||||
32 128 52 Untitled
|
||||
136 32 52 Untitled
|
||||
32 116 116 Untitled
|
||||
132 32 116 Untitled
|
||||
28 88 136 Untitled
|
||||
108 32 136 Untitled
|
||||
28 60 136 Untitled
|
||||
84 32 148 Untitled
|
||||
32 32 156 Untitled
|
||||
64 64 64 Untitled
|
||||
64 64 64 Untitled
|
||||
108 108 108 Untitled
|
||||
108 108 108 Untitled
|
||||
168 132 60 Untitled
|
||||
116 144 60 Untitled
|
||||
160 104 60 Untitled
|
||||
60 152 80 Untitled
|
||||
160 60 80 Untitled
|
||||
60 140 140 Untitled
|
||||
148 60 136 Untitled
|
||||
56 116 160 Untitled
|
||||
128 60 160 Untitled
|
||||
56 88 160 Untitled
|
||||
108 60 168 Untitled
|
||||
60 60 176 Untitled
|
||||
108 108 108 Untitled
|
||||
108 108 108 Untitled
|
||||
144 144 144 Untitled
|
||||
144 144 144 Untitled
|
||||
188 156 88 Untitled
|
||||
140 172 88 Untitled
|
||||
180 132 88 Untitled
|
||||
88 176 108 Untitled
|
||||
180 88 108 Untitled
|
||||
88 164 164 Untitled
|
||||
168 88 156 Untitled
|
||||
80 140 180 Untitled
|
||||
148 88 180 Untitled
|
||||
80 116 180 Untitled
|
||||
128 88 188 Untitled
|
||||
88 88 192 Untitled
|
||||
144 144 144 Untitled
|
||||
144 144 144 Untitled
|
||||
176 176 176 Untitled
|
||||
176 176 176 Untitled
|
||||
204 172 112 Untitled
|
||||
160 192 112 Untitled
|
||||
200 152 112 Untitled
|
||||
112 196 132 Untitled
|
||||
200 112 132 Untitled
|
||||
112 184 184 Untitled
|
||||
180 112 176 Untitled
|
||||
104 164 200 Untitled
|
||||
164 112 200 Untitled
|
||||
104 136 200 Untitled
|
||||
148 112 204 Untitled
|
||||
112 112 208 Untitled
|
||||
176 176 176 Untitled
|
||||
176 176 176 Untitled
|
||||
200 200 200 Untitled
|
||||
200 200 200 Untitled
|
||||
220 192 132 Untitled
|
||||
176 212 132 Untitled
|
||||
220 172 132 Untitled
|
||||
132 216 156 Untitled
|
||||
220 132 156 Untitled
|
||||
132 200 200 Untitled
|
||||
196 132 192 Untitled
|
||||
124 184 220 Untitled
|
||||
180 132 220 Untitled
|
||||
124 160 220 Untitled
|
||||
168 132 220 Untitled
|
||||
132 132 224 Untitled
|
||||
200 200 200 Untitled
|
||||
200 200 200 Untitled
|
||||
220 220 220 Untitled
|
||||
220 220 220 Untitled
|
||||
236 208 156 Untitled
|
||||
192 232 156 Untitled
|
||||
236 192 156 Untitled
|
||||
156 232 180 Untitled
|
||||
236 156 180 Untitled
|
||||
156 220 220 Untitled
|
||||
208 156 208 Untitled
|
||||
144 204 236 Untitled
|
||||
196 156 236 Untitled
|
||||
144 180 236 Untitled
|
||||
184 156 236 Untitled
|
||||
156 156 236 Untitled
|
||||
220 220 220 Untitled
|
||||
220 220 220 Untitled
|
||||
236 236 236 Untitled
|
||||
236 236 236 Untitled
|
||||
252 224 176 Untitled
|
||||
212 252 176 Untitled
|
||||
252 212 176 Untitled
|
||||
176 252 200 Untitled
|
||||
252 176 200 Untitled
|
||||
176 236 236 Untitled
|
||||
224 176 224 Untitled
|
||||
164 224 252 Untitled
|
||||
212 176 252 Untitled
|
||||
164 200 252 Untitled
|
||||
200 176 252 Untitled
|
||||
176 176 252 Untitled
|
||||
236 236 236 Untitled
|
||||
236 236 236 Untitled
|
18
data/palettes/cga.gpl
Normal file
@ -0,0 +1,18 @@
|
||||
GIMP Palette
|
||||
#
|
||||
0 0 0 Untitled
|
||||
0 0 170 Untitled
|
||||
0 170 0 Untitled
|
||||
0 170 170 Untitled
|
||||
170 0 0 Untitled
|
||||
170 0 170 Untitled
|
||||
170 85 0 Untitled
|
||||
170 170 170 Untitled
|
||||
85 85 85 Untitled
|
||||
85 85 255 Untitled
|
||||
85 255 85 Untitled
|
||||
85 255 255 Untitled
|
||||
255 85 85 Untitled
|
||||
255 85 255 Untitled
|
||||
255 255 85 Untitled
|
||||
255 255 255 Untitled
|
130
data/palettes/commodore-plus4.gpl
Normal file
@ -0,0 +1,130 @@
|
||||
GIMP Palette
|
||||
#
|
||||
0 0 0 Untitled
|
||||
32 32 32 Untitled
|
||||
93 8 0 Untitled
|
||||
0 55 70 Untitled
|
||||
93 0 109 Untitled
|
||||
0 78 0 Untitled
|
||||
32 17 109 Untitled
|
||||
32 47 0 Untitled
|
||||
93 16 0 Untitled
|
||||
62 31 0 Untitled
|
||||
1 62 0 Untitled
|
||||
93 1 32 Untitled
|
||||
0 63 32 Untitled
|
||||
0 48 109 Untitled
|
||||
62 1 109 Untitled
|
||||
0 70 0 Untitled
|
||||
0 0 0 Untitled
|
||||
64 64 64 Untitled
|
||||
125 40 25 Untitled
|
||||
3 87 102 Untitled
|
||||
125 18 141 Untitled
|
||||
3 110 0 Untitled
|
||||
64 49 141 Untitled
|
||||
64 79 0 Untitled
|
||||
125 48 0 Untitled
|
||||
94 63 0 Untitled
|
||||
33 94 0 Untitled
|
||||
125 33 64 Untitled
|
||||
3 95 64 Untitled
|
||||
3 80 141 Untitled
|
||||
94 33 141 Untitled
|
||||
3 102 25 Untitled
|
||||
0 0 0 Untitled
|
||||
96 96 96 Untitled
|
||||
156 72 57 Untitled
|
||||
35 119 134 Untitled
|
||||
156 50 172 Untitled
|
||||
35 142 19 Untitled
|
||||
96 81 172 Untitled
|
||||
96 111 19 Untitled
|
||||
156 80 19 Untitled
|
||||
126 95 19 Untitled
|
||||
65 126 19 Untitled
|
||||
156 65 96 Untitled
|
||||
35 127 96 Untitled
|
||||
35 112 172 Untitled
|
||||
126 65 172 Untitled
|
||||
35 134 57 Untitled
|
||||
0 0 0 Untitled
|
||||
128 128 128 Untitled
|
||||
188 104 89 Untitled
|
||||
67 151 166 Untitled
|
||||
188 82 204 Untitled
|
||||
67 173 51 Untitled
|
||||
128 113 204 Untitled
|
||||
128 142 51 Untitled
|
||||
188 111 51 Untitled
|
||||
158 127 51 Untitled
|
||||
97 158 51 Untitled
|
||||
188 97 128 Untitled
|
||||
67 158 128 Untitled
|
||||
67 144 204 Untitled
|
||||
158 97 204 Untitled
|
||||
67 166 89 Untitled
|
||||
0 0 0 Untitled
|
||||
159 159 159 Untitled
|
||||
220 136 121 Untitled
|
||||
99 183 198 Untitled
|
||||
220 113 236 Untitled
|
||||
99 205 83 Untitled
|
||||
159 144 236 Untitled
|
||||
159 174 83 Untitled
|
||||
220 143 83 Untitled
|
||||
190 159 83 Untitled
|
||||
129 190 83 Untitled
|
||||
220 128 159 Untitled
|
||||
99 190 159 Untitled
|
||||
99 175 236 Untitled
|
||||
190 129 236 Untitled
|
||||
99 198 121 Untitled
|
||||
0 0 0 Untitled
|
||||
191 191 191 Untitled
|
||||
252 168 153 Untitled
|
||||
130 215 230 Untitled
|
||||
252 145 255 Untitled
|
||||
130 237 114 Untitled
|
||||
191 176 255 Untitled
|
||||
191 206 114 Untitled
|
||||
252 175 114 Untitled
|
||||
222 191 114 Untitled
|
||||
161 222 114 Untitled
|
||||
252 160 191 Untitled
|
||||
130 222 191 Untitled
|
||||
130 207 255 Untitled
|
||||
222 161 255 Untitled
|
||||
130 230 153 Untitled
|
||||
0 0 0 Untitled
|
||||
223 223 223 Untitled
|
||||
255 200 185 Untitled
|
||||
162 247 255 Untitled
|
||||
255 177 255 Untitled
|
||||
162 255 146 Untitled
|
||||
223 208 255 Untitled
|
||||
223 238 146 Untitled
|
||||
255 207 146 Untitled
|
||||
254 223 146 Untitled
|
||||
193 254 146 Untitled
|
||||
255 192 223 Untitled
|
||||
162 254 223 Untitled
|
||||
162 239 255 Untitled
|
||||
254 193 255 Untitled
|
||||
162 255 185 Untitled
|
||||
0 0 0 Untitled
|
||||
255 255 255 Untitled
|
||||
255 232 217 Untitled
|
||||
194 255 255 Untitled
|
||||
255 209 255 Untitled
|
||||
194 255 178 Untitled
|
||||
255 240 255 Untitled
|
||||
255 255 178 Untitled
|
||||
255 239 178 Untitled
|
||||
255 254 178 Untitled
|
||||
225 255 178 Untitled
|
||||
255 224 255 Untitled
|
||||
194 255 255 Untitled
|
||||
194 255 255 Untitled
|
||||
255 225 255 Untitled
|
||||
194 255 217 Untitled
|
18
data/palettes/commodore-vic20.gpl
Normal file
@ -0,0 +1,18 @@
|
||||
GIMP Palette
|
||||
#
|
||||
0 0 0 Untitled
|
||||
255 255 255 Untitled
|
||||
120 41 34 Untitled
|
||||
135 214 221 Untitled
|
||||
170 95 182 Untitled
|
||||
26 130 38 Untitled
|
||||
64 49 141 Untitled
|
||||
191 206 114 Untitled
|
||||
170 116 73 Untitled
|
||||
234 180 137 Untitled
|
||||
184 105 98 Untitled
|
||||
199 255 255 Untitled
|
||||
234 159 246 Untitled
|
||||
148 224 137 Untitled
|
||||
128 113 204 Untitled
|
||||
255 255 178 Untitled
|
18
data/palettes/commodore64.gpl
Normal file
@ -0,0 +1,18 @@
|
||||
GIMP Palette
|
||||
#
|
||||
0 0 0 Untitled
|
||||
255 255 255 Untitled
|
||||
136 57 50 Untitled
|
||||
103 182 189 Untitled
|
||||
139 63 150 Untitled
|
||||
85 160 73 Untitled
|
||||
64 49 141 Untitled
|
||||
191 206 114 Untitled
|
||||
139 84 41 Untitled
|
||||
87 66 0 Untitled
|
||||
184 105 98 Untitled
|
||||
80 80 80 Untitled
|
||||
120 120 120 Untitled
|
||||
148 224 137 Untitled
|
||||
120 105 196 Untitled
|
||||
159 159 159 Untitled
|
6
data/palettes/gameboy.gpl
Normal file
@ -0,0 +1,6 @@
|
||||
GIMP Palette
|
||||
#
|
||||
155 188 15 Untitled
|
||||
139 172 15 Untitled
|
||||
48 98 48 Untitled
|
||||
15 56 15 Untitled
|
34
data/palettes/master-system.gpl
Normal file
@ -0,0 +1,34 @@
|
||||
GIMP Palette
|
||||
#
|
||||
85 0 85 Untitled
|
||||
170 85 170 Untitled
|
||||
255 170 255 Untitled
|
||||
0 0 85 Untitled
|
||||
85 85 170 Untitled
|
||||
170 170 255 Untitled
|
||||
85 170 170 Untitled
|
||||
0 85 85 Untitled
|
||||
170 255 255 Untitled
|
||||
0 85 0 Untitled
|
||||
170 255 170 Untitled
|
||||
85 170 0 Untitled
|
||||
170 255 0 Untitled
|
||||
170 170 0 Untitled
|
||||
85 85 0 Untitled
|
||||
255 255 85 Untitled
|
||||
170 170 85 Untitled
|
||||
255 255 170 Untitled
|
||||
255 170 0 Untitled
|
||||
170 85 0 Untitled
|
||||
255 170 85 Untitled
|
||||
255 85 0 Untitled
|
||||
255 0 0 Untitled
|
||||
170 0 0 Untitled
|
||||
85 0 0 Untitled
|
||||
255 85 85 Untitled
|
||||
170 85 85 Untitled
|
||||
255 170 170 Untitled
|
||||
255 255 255 Untitled
|
||||
170 170 170 Untitled
|
||||
85 85 85 Untitled
|
||||
0 0 0 Untitled
|
66
data/palettes/nes.gpl
Normal file
@ -0,0 +1,66 @@
|
||||
GIMP Palette
|
||||
#
|
||||
125 125 125 Untitled
|
||||
0 0 255 Untitled
|
||||
0 0 190 Untitled
|
||||
69 40 190 Untitled
|
||||
150 0 134 Untitled
|
||||
170 0 32 Untitled
|
||||
170 16 0 Untitled
|
||||
138 20 0 Untitled
|
||||
81 48 0 Untitled
|
||||
0 121 0 Untitled
|
||||
0 105 0 Untitled
|
||||
0 89 0 Untitled
|
||||
0 65 89 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
190 190 190 Untitled
|
||||
0 121 251 Untitled
|
||||
0 89 251 Untitled
|
||||
105 69 255 Untitled
|
||||
219 0 207 Untitled
|
||||
231 0 89 Untitled
|
||||
251 56 0 Untitled
|
||||
231 93 16 Untitled
|
||||
174 125 0 Untitled
|
||||
0 186 0 Untitled
|
||||
0 170 0 Untitled
|
||||
0 170 69 Untitled
|
||||
0 138 138 Untitled
|
||||
8 8 8 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
251 251 251 Untitled
|
||||
60 190 255 Untitled
|
||||
105 138 255 Untitled
|
||||
154 121 251 Untitled
|
||||
251 121 251 Untitled
|
||||
251 89 154 Untitled
|
||||
251 121 89 Untitled
|
||||
255 162 69 Untitled
|
||||
251 186 0 Untitled
|
||||
186 251 24 Untitled
|
||||
89 219 85 Untitled
|
||||
89 251 154 Untitled
|
||||
0 235 219 Untitled
|
||||
121 121 121 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
||||
255 255 255 Untitled
|
||||
166 231 255 Untitled
|
||||
186 186 251 Untitled
|
||||
219 186 251 Untitled
|
||||
251 186 251 Untitled
|
||||
251 166 195 Untitled
|
||||
243 211 178 Untitled
|
||||
255 227 170 Untitled
|
||||
251 219 121 Untitled
|
||||
219 251 121 Untitled
|
||||
186 251 186 Untitled
|
||||
186 251 219 Untitled
|
||||
0 255 255 Untitled
|
||||
219 219 219 Untitled
|
||||
0 0 0 Untitled
|
||||
0 0 0 Untitled
|
10
data/palettes/teletext.gpl
Normal file
@ -0,0 +1,10 @@
|
||||
GIMP Palette
|
||||
#
|
||||
0 0 0 Untitled
|
||||
0 0 255 Untitled
|
||||
255 0 0 Untitled
|
||||
255 0 255 Untitled
|
||||
0 255 0 Untitled
|
||||
0 255 255 Untitled
|
||||
255 255 0 Untitled
|
||||
255 255 255 Untitled
|
18
data/palettes/win16.gpl
Normal file
@ -0,0 +1,18 @@
|
||||
GIMP Palette
|
||||
#
|
||||
0 0 0 Untitled
|
||||
130 0 0 Untitled
|
||||
0 130 0 Untitled
|
||||
130 130 0 Untitled
|
||||
0 0 130 Untitled
|
||||
130 0 130 Untitled
|
||||
0 130 130 Untitled
|
||||
195 195 195 Untitled
|
||||
130 130 130 Untitled
|
||||
255 0 0 Untitled
|
||||
0 255 0 Untitled
|
||||
255 255 0 Untitled
|
||||
0 0 255 Untitled
|
||||
255 0 255 Untitled
|
||||
0 255 255 Untitled
|
||||
255 255 255 Untitled
|
20
data/palettes/zx-spectrum.gpl
Normal file
@ -0,0 +1,20 @@
|
||||
GIMP Palette
|
||||
#
|
||||
# ZX Spectrum
|
||||
#
|
||||
0 0 0 Black
|
||||
0 0 192 Basic Blue
|
||||
192 0 0 Basic Red
|
||||
192 0 192 Basic Magenta
|
||||
0 192 0 Basic Green
|
||||
0 192 192 Basic Cyan
|
||||
192 192 0 Basic Yellow
|
||||
192 192 192 Basic White
|
||||
0 0 0 Black
|
||||
0 0 255 Bright Blue
|
||||
255 0 0 Bright Red
|
||||
255 0 255 Bright Magenta
|
||||
0 255 0 Bright Green
|
||||
0 255 255 Bright Cyan
|
||||
255 255 0 Bright Yellow
|
||||
255 255 255 Bright White
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 12 KiB |
@ -77,6 +77,9 @@
|
||||
<color id="timeline_padding" value="#7d929e" />
|
||||
<color id="status_bar_text" value="#2e3234" />
|
||||
<color id="status_bar_face" value="#7d929e" />
|
||||
<color id="flag_normal" value="#d3cbbe" />
|
||||
<color id="flag_active" value="#ff0000" />
|
||||
<color id="flag_clicked" value="#7d929e" />
|
||||
</colors>
|
||||
|
||||
<cursors>
|
||||
@ -317,6 +320,14 @@
|
||||
<part id="timeline_padding_br" x="288" y="24" w1="1" w2="10" w3="1" h1="1" h2="10" h3="1" />
|
||||
<part id="timeline_drop_layer_deco" x="252" y="127" w1="3" w2="1" w3="3" h1="2" h2="1" h3="2" />
|
||||
<part id="timeline_drop_frame_deco" x="252" y="120" w1="2" w2="1" w3="2" h1="3" h2="1" h3="3" />
|
||||
<part id="timeline_loop_range" x="240" y="132" w1="3" w2="6" w3="3" h1="3" h2="6" h3="3" />
|
||||
<part id="flag_normal" x="0" y="240" w="16" h="10" />
|
||||
<part id="flag_highlight" x="16" y="240" w="16" h="10" />
|
||||
<part id="drop_pixels_ok" x="176" y="176" w="7" h="8" />
|
||||
<part id="drop_pixels_ok_selected" x="176" y="184" w="7" h="8" />
|
||||
<part id="drop_pixels_cancel" x="192" y="176" w="7" h="8" />
|
||||
<part id="drop_pixels_cancel_selected" x="192" y="184" w="7" h="8" />
|
||||
<part id="warning_box" x="112" y="80" w="9" h="10" />
|
||||
</parts>
|
||||
|
||||
<stylesheet>
|
||||
@ -519,6 +530,31 @@
|
||||
<background part="timeline_drop_frame_deco" />
|
||||
</style>
|
||||
|
||||
<!-- timeline_loop_range -->
|
||||
<style id="timeline_loop_range">
|
||||
<background part="timeline_loop_range" />
|
||||
</style>
|
||||
|
||||
<!-- flag -->
|
||||
<style id="flag">
|
||||
<background part="flag_normal" color="flag_normal" />
|
||||
</style>
|
||||
<style id="flag:active">
|
||||
<background part="flag_highlight" color="flag_active" />
|
||||
</style>
|
||||
<style id="flag:clicked">
|
||||
<background part="flag_highlight" color="flag_clicked" />
|
||||
</style>
|
||||
|
||||
<!-- warning_box -->
|
||||
<style id="warning_box">
|
||||
<background color="face" />
|
||||
<icon part="warning_box" align="center" valign="middle" />
|
||||
</style>
|
||||
<style id="warning_box:hover">
|
||||
<background color="hot_face" />
|
||||
</style>
|
||||
|
||||
</stylesheet>
|
||||
|
||||
</skin>
|
||||
|
@ -15,11 +15,11 @@
|
||||
<separator text="Color Mode:" left="true" horizontal="true" />
|
||||
<box vertical="true" homogeneous="true" childspacing="0">
|
||||
<box horizontal="true">
|
||||
<radio id="radio3" text="&Indexed with " group="1" tooltip="Using a palette of 256 colors (8 bits per pixel)" />
|
||||
<entry id="colors" maxsize="8" tooltip="Maximum number of colors (only for Indexed images) This field cannot be modified in this beta version." disabled="true" />
|
||||
<label text="Colors" />
|
||||
<radio id="radio3" text="&Indexed color" group="1" tooltip="Using a palette of 256 colors (8 bits per pixel)" />
|
||||
<!-- <entry id="colors" maxsize="8" tooltip="Maximum number of colors (only for Indexed images) This field cannot be modified in this beta version." disabled="true" /> -->
|
||||
<!-- <label text="Colors" /> -->
|
||||
</box>
|
||||
<radio id="radio1" text="&RGB Color" group="1" tooltip="RGBA color mode (32 bits per pixel)" />
|
||||
<radio id="radio1" text="&RGB color" group="1" tooltip="RGBA color mode (32 bits per pixel)" />
|
||||
<radio id="radio2" text="&Grayscale" group="1" tooltip="Value and Alpha (16 bits per pixel)" />
|
||||
</box>
|
||||
|
||||
|
@ -2,32 +2,29 @@
|
||||
<!-- Copyright (C) 2001-2013 by David Capello -->
|
||||
<gui>
|
||||
<window text="Sprite Properties" id="sprite_properties">
|
||||
<box vertical="true">
|
||||
<box horizontal="true">
|
||||
<grid columns="2" expansive="true">
|
||||
<vbox>
|
||||
<grid columns="2">
|
||||
<label text="File name:" />
|
||||
<entry text="" id="name" maxsize="256" minwidth="64" readonly="true" cell_align="horizontal" />
|
||||
|
||||
<label text="File name:" />
|
||||
<entry text="" id="name" maxsize="256" minwidth="64" readonly="true" cell_align="horizontal" />
|
||||
<label text="Type:" />
|
||||
<label text="" id="type" />
|
||||
|
||||
<label text="Type:" />
|
||||
<label text="" id="type" />
|
||||
<label text="Size:" />
|
||||
<label text="" id="size" />
|
||||
|
||||
<label text="Size:" />
|
||||
<label text="" id="size" />
|
||||
<label text="Frames:" />
|
||||
<label text="" id="frames" />
|
||||
|
||||
<label text="Frames:" />
|
||||
<label text="" id="frames" />
|
||||
|
||||
<label text="Transparent Color:" />
|
||||
<box horizontal="true" id="box_transparent" tooltip="Palette entry used as transparent color in each layer (only for indexed images)." />
|
||||
</grid>
|
||||
</box>
|
||||
<label text="Transparent Color:" />
|
||||
<hbox id="box_transparent" tooltip="Palette entry used as transparent color in each layer (only for indexed images)." />
|
||||
</grid>
|
||||
<separator horizontal="true" />
|
||||
<box horizontal="true">
|
||||
<box horizontal="true" expansive="true" />
|
||||
<hbox>
|
||||
<boxfiller />
|
||||
<button text="&OK" closewindow="true" id="ok" magnet="true" width="60" />
|
||||
<button text="&Cancel" closewindow="true" id="cancel" width="60" />
|
||||
</box>
|
||||
</box>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</window>
|
||||
</gui>
|
||||
|
31
data/widgets/timeline_conf.xml
Normal file
@ -0,0 +1,31 @@
|
||||
<!-- ASEPRITE -->
|
||||
<!-- Copyright (C) 2014 by David Capello -->
|
||||
<gui>
|
||||
<vbox id="mainbox">
|
||||
<separator cell_hspan="2" text="Onion Skin:" left="true" horizontal="true" />
|
||||
<grid columns="2">
|
||||
<hbox cell_hspan="2">
|
||||
<radio group="1" text="Merge Frames" id="merge" />
|
||||
<radio group="1" text="Red/Blue Tint" id="tint" />
|
||||
<button id="reset_onionskin" text="Reset" width="60" />
|
||||
</hbox>
|
||||
|
||||
<label text="Opacity:" />
|
||||
<slider min="0" max="255" id="opacity" cell_align="horizontal" width="128" />
|
||||
|
||||
<label text="Opacity Step:" />
|
||||
<slider min="0" max="255" id="opacity_step" cell_align="horizontal" width="128" />
|
||||
</grid>
|
||||
|
||||
<separator text="Loop:" left="true" horizontal="true" />
|
||||
<hbox cell_hspan="2">
|
||||
<radio group="2" text="Normal" id="normal" />
|
||||
<radio group="2" text="Reverse" id="reverse" />
|
||||
<radio group="2" text="Ping-pong" id="pingpong" />
|
||||
</hbox>
|
||||
<hbox cell_hspan="2">
|
||||
<button id="loop_section" text="Set Loop Section" expansive="true" tooltip="Select a range of frames in the timeline and then press this button." />
|
||||
<button id="reset_loop_section" text="Reset Loop Section" />
|
||||
</hbox>
|
||||
</vbox>
|
||||
</gui>
|
@ -16,14 +16,6 @@ if [ ! -d $destdir ] ; then
|
||||
git clone --depth=1 $srcdir $destdir
|
||||
fi
|
||||
|
||||
# ----------------------------
|
||||
# Copy the quick reference PDF
|
||||
# ----------------------------
|
||||
|
||||
if [ ! -f $destdir/docs ] ; then
|
||||
cp $srcdir/docs/quickref.pdf $destdir/docs
|
||||
fi
|
||||
|
||||
# --------------
|
||||
# Update version
|
||||
# --------------
|
||||
|
@ -92,6 +92,10 @@ if (CMAKE_USE_PTHREADS_INIT)
|
||||
set(sys_libs ${sys_libs} ${CMAKE_THREAD_LIBS_INIT})
|
||||
endif()
|
||||
|
||||
if(NOT "${CUSTOM_WEBSITE_URL}" STREQUAL "")
|
||||
add_definitions(-DCUSTOM_WEBSITE_URL="${CUSTOM_WEBSITE_URL}")
|
||||
endif()
|
||||
|
||||
if(ENABLE_UPDATER)
|
||||
if(USE_SHARED_CURL)
|
||||
find_library(LIBCURL_LIBRARY NAMES curl)
|
||||
|
@ -10,3 +10,5 @@ Changes:
|
||||
* Added resize support for Windows, X11, and Mac OS X ports.
|
||||
* Removed code and functions that are not used (Allegro GUI,
|
||||
audio, MIDI, joystick, etc.).
|
||||
* The HWND class has CS_DBLCLKS enabled (so UI code can detect
|
||||
double-clicks from Windows messages).
|
||||
|
@ -205,7 +205,7 @@ static void paint_win(RECT *rect)
|
||||
/* we may have lost the DirectDraw surfaces
|
||||
* (e.g after the monitor has gone to low power)
|
||||
*/
|
||||
if (IDirectDrawSurface2_IsLost(gfx_directx_primary_surface->id))
|
||||
if (IDirectDrawSurface2_IsLost(gfx_directx_primary_surface->id) == DDERR_SURFACELOST)
|
||||
switch_in_win();
|
||||
|
||||
/* clip the rectangle */
|
||||
|
@ -427,7 +427,7 @@ static HWND create_directx_window(void)
|
||||
|
||||
if (first) {
|
||||
/* setup the window class */
|
||||
wnd_class.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wnd_class.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
|
||||
wnd_class.lpfnWndProc = directx_wnd_proc;
|
||||
wnd_class.cbClsExtra = 0;
|
||||
wnd_class.cbWndExtra = 0;
|
||||
|
@ -18,8 +18,8 @@ add_library(app-lib
|
||||
commands/cmd_canvas_size.cpp
|
||||
commands/cmd_cel_properties.cpp
|
||||
commands/cmd_change_color.cpp
|
||||
commands/cmd_change_image_type.cpp
|
||||
commands/cmd_change_pen.cpp
|
||||
commands/cmd_change_pixel_format.cpp
|
||||
commands/cmd_clear.cpp
|
||||
commands/cmd_close_file.cpp
|
||||
commands/cmd_configure_tools.cpp
|
||||
@ -56,6 +56,7 @@ add_library(app-lib
|
||||
commands/cmd_new_frame.cpp
|
||||
commands/cmd_new_layer.cpp
|
||||
commands/cmd_new_layer_set.cpp
|
||||
commands/cmd_onionskin.cpp
|
||||
commands/cmd_open_file.cpp
|
||||
commands/cmd_open_in_folder.cpp
|
||||
commands/cmd_open_with_app.cpp
|
||||
@ -125,6 +126,7 @@ add_library(app-lib
|
||||
flatten.cpp
|
||||
gfxmode.cpp
|
||||
gui_xml.cpp
|
||||
handle_anidir.cpp
|
||||
ini_file.cpp
|
||||
job.cpp
|
||||
launcher.cpp
|
||||
@ -154,7 +156,9 @@ add_library(app-lib
|
||||
ui/color_button.cpp
|
||||
ui/color_selector.cpp
|
||||
ui/color_sliders.cpp
|
||||
ui/configure_timeline_popup.cpp
|
||||
ui/context_bar.cpp
|
||||
ui/devconsole_view.cpp
|
||||
ui/document_view.cpp
|
||||
ui/drop_down_button.cpp
|
||||
ui/editor/cursor.cpp
|
||||
@ -179,6 +183,7 @@ add_library(app-lib
|
||||
ui/main_menu_bar.cpp
|
||||
ui/main_window.cpp
|
||||
ui/mini_editor.cpp
|
||||
ui/notifications.cpp
|
||||
ui/palette_listbox.cpp
|
||||
ui/palette_popup.cpp
|
||||
ui/palette_view.cpp
|
||||
@ -228,6 +233,7 @@ add_library(app-lib
|
||||
undoers/set_palette_colors.cpp
|
||||
undoers/set_sprite_pixel_format.cpp
|
||||
undoers/set_sprite_size.cpp
|
||||
undoers/set_sprite_transparent_color.cpp
|
||||
undoers/set_stock_pixel_format.cpp
|
||||
undoers/set_total_frames.cpp
|
||||
util/autocrop.cpp
|
||||
|
@ -145,9 +145,9 @@ App::App(int argc, const char* argv[])
|
||||
RenderEngine::loadConfig();
|
||||
|
||||
// Default palette.
|
||||
base::string palFile(!options.paletteFileName().empty() ?
|
||||
options.paletteFileName():
|
||||
base::string(get_config_string("GfxMode", "Palette", "")));
|
||||
std::string palFile(!options.paletteFileName().empty() ?
|
||||
options.paletteFileName():
|
||||
std::string(get_config_string("GfxMode", "Palette", "")));
|
||||
|
||||
if (palFile.empty()) {
|
||||
// Try to use a default pixel art palette.
|
||||
@ -294,6 +294,9 @@ App::~App()
|
||||
// Remove Aseprite handlers
|
||||
PRINTF("ASE: Uninstalling\n");
|
||||
|
||||
// Delete file formats.
|
||||
FileFormatsManager::destroyInstance();
|
||||
|
||||
// Fire App Exit signal.
|
||||
App::instance()->Exit();
|
||||
|
||||
@ -328,6 +331,11 @@ RecentFiles* App::getRecentFiles() const
|
||||
return &m_modules->m_recent_files;
|
||||
}
|
||||
|
||||
void App::showNotification(const char* text, const char* url)
|
||||
{
|
||||
m_mainWindow->showNotification(text, url);
|
||||
}
|
||||
|
||||
// Updates palette and redraw the screen.
|
||||
void app_refresh_screen()
|
||||
{
|
||||
@ -374,12 +382,15 @@ void app_default_statusbar_message()
|
||||
|
||||
int app_get_color_to_clear_layer(Layer* layer)
|
||||
{
|
||||
/* all transparent layers are cleared with the mask color */
|
||||
app::Color color = app::Color::fromMask();
|
||||
ASSERT(layer != NULL);
|
||||
|
||||
/* the `Background' is erased with the `Background Color' */
|
||||
if (layer != NULL && layer->isBackground())
|
||||
app::Color color;
|
||||
|
||||
// The `Background' is erased with the `Background Color'
|
||||
if (layer->isBackground())
|
||||
color = ColorBar::instance()->getBgColor();
|
||||
else // All transparent layers are cleared with the mask color
|
||||
color = app::Color::fromMask();
|
||||
|
||||
return color_utils::color_for_layer(color, layer);
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "base/unique_ptr.h"
|
||||
#include "raster/pixel_format.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace ui {
|
||||
@ -70,6 +71,8 @@ namespace app {
|
||||
RecentFiles* getRecentFiles() const;
|
||||
MainWindow* getMainWindow() const { return m_mainWindow; }
|
||||
|
||||
void showNotification(const char* text, const char* url);
|
||||
|
||||
// App Signals
|
||||
Signal0<void> Exit;
|
||||
Signal0<void> PaletteChange;
|
||||
@ -80,7 +83,7 @@ namespace app {
|
||||
Signal0<void> CurrentToolChange;
|
||||
|
||||
private:
|
||||
typedef std::vector<base::string> FileList;
|
||||
typedef std::vector<std::string> FileList;
|
||||
class Modules;
|
||||
|
||||
static App* m_instance;
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
namespace app {
|
||||
|
||||
Backup::Backup(const base::string& path)
|
||||
Backup::Backup(const std::string& path)
|
||||
: m_path(path)
|
||||
{
|
||||
}
|
||||
|
@ -21,14 +21,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "base/disable_copying.h"
|
||||
#include "base/string.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace app {
|
||||
|
||||
// A class to record/restore backup information.
|
||||
class Backup {
|
||||
public:
|
||||
Backup(const base::string& path);
|
||||
Backup(const std::string& path);
|
||||
~Backup();
|
||||
|
||||
// Returns true if there are items that can be restored.
|
||||
@ -37,7 +38,7 @@ namespace app {
|
||||
private:
|
||||
DISABLE_COPYING(Backup);
|
||||
|
||||
base::string m_path;
|
||||
std::string m_path;
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
@ -24,8 +24,8 @@
|
||||
|
||||
#include "app/check_update.h"
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/ini_file.h"
|
||||
#include "app/ui/status_bar.h"
|
||||
#include "base/bind.h"
|
||||
|
||||
#include <ctime>
|
||||
@ -169,7 +169,7 @@ void CheckUpdateThreadLauncher::onMonitoringTick()
|
||||
|
||||
case updater::CheckUpdateResponse::Critical:
|
||||
case updater::CheckUpdateResponse::Major:
|
||||
StatusBar::instance()->showNotification("New Version!", m_response.getUrl().c_str());
|
||||
App::instance()->showNotification("New Version Available!", m_response.getUrl().c_str());
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -601,14 +601,10 @@ int Color::getIndex() const
|
||||
return 0;
|
||||
|
||||
case Color::RgbType:
|
||||
PRINTF("Getting `index' from a RGB color\n"); // TODO
|
||||
ASSERT(false);
|
||||
break;
|
||||
return get_current_palette()->findBestfit(getRed(), getGreen(), getBlue());
|
||||
|
||||
case Color::HsvType:
|
||||
PRINTF("Getting `index' from a HSV color\n"); // TODO
|
||||
ASSERT(false);
|
||||
break;
|
||||
return get_current_palette()->findBestfit(getRed(), getGreen(), getBlue());
|
||||
|
||||
case Color::GrayType:
|
||||
return m_value.gray;
|
||||
|
64
src/app/color_target.h
Normal file
@ -0,0 +1,64 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2014 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef APP_COLOR_TARGET_H_INCLUDED
|
||||
#define APP_COLOR_TARGET_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "raster/color.h"
|
||||
#include "raster/layer.h"
|
||||
#include "raster/pixel_format.h"
|
||||
#include "raster/sprite.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
// Represents the kind of surface where we'll use a color.
|
||||
class ColorTarget {
|
||||
public:
|
||||
enum LayerType {
|
||||
BackgroundLayer,
|
||||
TransparentLayer
|
||||
};
|
||||
|
||||
ColorTarget(LayerType layerType, raster::PixelFormat pixelFormat, raster::color_t maskColor) :
|
||||
m_layerType(layerType),
|
||||
m_pixelFormat(pixelFormat),
|
||||
m_maskColor(maskColor) {
|
||||
}
|
||||
|
||||
ColorTarget(raster::Layer* layer) :
|
||||
m_layerType(layer->isBackground() ? BackgroundLayer: TransparentLayer),
|
||||
m_pixelFormat(layer->getSprite()->getPixelFormat()),
|
||||
m_maskColor(layer->getSprite()->getTransparentColor()) {
|
||||
}
|
||||
|
||||
bool isBackground() const { return m_layerType == BackgroundLayer; }
|
||||
bool isTransparent() const { return m_layerType == TransparentLayer; }
|
||||
LayerType layerType() const { return m_layerType; }
|
||||
raster::PixelFormat pixelFormat() const { return m_pixelFormat; }
|
||||
raster::color_t maskColor() const { return m_maskColor; }
|
||||
|
||||
private:
|
||||
LayerType m_layerType;
|
||||
raster::PixelFormat m_pixelFormat;
|
||||
raster::color_t m_maskColor;
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
||||
#endif
|
@ -1,5 +1,5 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2013 David Capello
|
||||
* Copyright (C) 2001-2014 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -168,10 +168,7 @@ raster::color_t color_utils::color_for_image(const app::Color& color, PixelForma
|
||||
c = graya(color.getGray(), 255);
|
||||
break;
|
||||
case IMAGE_INDEXED:
|
||||
if (color.getType() == app::Color::IndexType)
|
||||
c = color.getIndex();
|
||||
else
|
||||
c = get_current_palette()->findBestfit(color.getRed(), color.getGreen(), color.getBlue());
|
||||
c = color.getIndex();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -180,44 +177,40 @@ raster::color_t color_utils::color_for_image(const app::Color& color, PixelForma
|
||||
|
||||
raster::color_t color_utils::color_for_layer(const app::Color& color, Layer* layer)
|
||||
{
|
||||
raster::color_t pixel_color;
|
||||
|
||||
if (color.getType() == app::Color::MaskType) {
|
||||
pixel_color = layer->getSprite()->getTransparentColor();
|
||||
}
|
||||
else {
|
||||
PixelFormat format = layer->getSprite()->getPixelFormat();
|
||||
pixel_color = color_for_image(color, format);
|
||||
}
|
||||
|
||||
return fixup_color_for_layer(layer, pixel_color);
|
||||
return color_for_target(color, ColorTarget(layer));
|
||||
}
|
||||
|
||||
raster::color_t color_utils::fixup_color_for_layer(Layer *layer, raster::color_t color)
|
||||
raster::color_t color_utils::color_for_target(const app::Color& color, const ColorTarget& colorTarget)
|
||||
{
|
||||
if (layer->isBackground())
|
||||
return fixup_color_for_background(layer->getSprite()->getPixelFormat(), color);
|
||||
else
|
||||
return color;
|
||||
}
|
||||
if (color.getType() == app::Color::MaskType)
|
||||
return colorTarget.maskColor();
|
||||
|
||||
raster::color_t color_utils::fixup_color_for_background(PixelFormat format, raster::color_t color)
|
||||
{
|
||||
switch (format) {
|
||||
raster::color_t c = -1;
|
||||
|
||||
switch (colorTarget.pixelFormat()) {
|
||||
case IMAGE_RGB:
|
||||
if (rgba_geta(color) < 255) {
|
||||
return rgba(rgba_getr(color),
|
||||
rgba_getg(color),
|
||||
rgba_getb(color), 255);
|
||||
}
|
||||
c = rgba(color.getRed(), color.getGreen(), color.getBlue(), 255);
|
||||
break;
|
||||
case IMAGE_GRAYSCALE:
|
||||
if (graya_geta(color) < 255) {
|
||||
return graya(graya_getv(color), 255);
|
||||
c = graya(color.getGray(), 255);
|
||||
break;
|
||||
case IMAGE_INDEXED:
|
||||
if (color.getType() == app::Color::IndexType) {
|
||||
c = color.getIndex();
|
||||
}
|
||||
else {
|
||||
c = get_current_palette()->findBestfit(
|
||||
color.getRed(),
|
||||
color.getGreen(),
|
||||
color.getBlue(),
|
||||
colorTarget.isTransparent() ?
|
||||
colorTarget.maskColor(): // Don't return the mask color
|
||||
-1); // Return any color, we are in a background layer.
|
||||
}
|
||||
break;
|
||||
}
|
||||
return color;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2013 David Capello
|
||||
* Copyright (C) 2001-2014 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -21,6 +21,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "app/color.h"
|
||||
#include "app/color_target.h"
|
||||
#include "raster/color.h"
|
||||
#include "raster/pixel_format.h"
|
||||
#include "ui/color.h"
|
||||
@ -39,9 +40,7 @@ namespace app {
|
||||
int color_for_allegro(const app::Color& color, int depth);
|
||||
raster::color_t color_for_image(const app::Color& color, raster::PixelFormat format);
|
||||
raster::color_t color_for_layer(const app::Color& color, raster::Layer* layer);
|
||||
|
||||
raster::color_t fixup_color_for_layer(raster::Layer* layer, raster::color_t color);
|
||||
raster::color_t fixup_color_for_background(raster::PixelFormat format, raster::color_t color);
|
||||
raster::color_t color_for_target(const app::Color& color, const ColorTarget& colorTarget);
|
||||
|
||||
} // namespace color_utils
|
||||
} // namespace app
|
||||
|
@ -68,16 +68,22 @@ void BackgroundFromLayerCommand::onExecute(Context* context)
|
||||
Document* document(writer.document());
|
||||
Sprite* sprite(writer.sprite());
|
||||
|
||||
// each frame of the layer to be converted as `Background' must be
|
||||
// cleared using the selected background color in the color-bar
|
||||
int bgcolor = color_utils::color_for_image(context->getSettings()->getBgColor(), sprite->getPixelFormat());
|
||||
bgcolor = color_utils::fixup_color_for_background(sprite->getPixelFormat(), bgcolor);
|
||||
raster::color_t bgcolor =
|
||||
color_utils::color_for_target(
|
||||
context->getSettings()->getBgColor(),
|
||||
ColorTarget(
|
||||
ColorTarget::BackgroundLayer,
|
||||
sprite->getPixelFormat(),
|
||||
sprite->getTransparentColor()));
|
||||
|
||||
{
|
||||
UndoTransaction undo_transaction(writer.context(), "Background from Layer");
|
||||
document->getApi().backgroundFromLayer(static_cast<LayerImage*>(writer.layer()), bgcolor);
|
||||
document->getApi().backgroundFromLayer(
|
||||
static_cast<LayerImage*>(writer.layer()),
|
||||
bgcolor);
|
||||
undo_transaction.commit();
|
||||
}
|
||||
|
||||
update_screen_for_document(document);
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "app/commands/command.h"
|
||||
|
||||
#include "app/commands/commands.h"
|
||||
#include "app/commands/params.h"
|
||||
#include "app/context.h"
|
||||
#include "base/compiler_specific.h"
|
||||
|
||||
@ -30,26 +31,52 @@ namespace app {
|
||||
|
||||
class CancelCommand : public Command {
|
||||
public:
|
||||
enum Type {
|
||||
NoOp,
|
||||
All,
|
||||
};
|
||||
|
||||
CancelCommand();
|
||||
Command* clone() const OVERRIDE { return new CancelCommand(*this); }
|
||||
|
||||
protected:
|
||||
void onLoadParams(Params* params);
|
||||
void onExecute(Context* context);
|
||||
|
||||
private:
|
||||
Type m_type;
|
||||
};
|
||||
|
||||
CancelCommand::CancelCommand()
|
||||
: Command("Cancel",
|
||||
"Cancel",
|
||||
CmdUIOnlyFlag)
|
||||
, m_type(NoOp)
|
||||
{
|
||||
}
|
||||
|
||||
void CancelCommand::onLoadParams(Params* params)
|
||||
{
|
||||
std::string type = params->get("type");
|
||||
if (type == "noop") m_type = NoOp;
|
||||
else if (type == "all") m_type = All;
|
||||
}
|
||||
|
||||
void CancelCommand::onExecute(Context* context)
|
||||
{
|
||||
if (context->checkFlags(ContextFlags::ActiveDocumentIsWritable |
|
||||
ContextFlags::HasVisibleMask)) {
|
||||
Command* cmd = CommandsModule::instance()->getCommandByName(CommandId::DeselectMask);
|
||||
context->executeCommand(cmd);
|
||||
switch (m_type) {
|
||||
|
||||
case NoOp:
|
||||
// Do nothing.
|
||||
break;
|
||||
|
||||
case All:
|
||||
if (context->checkFlags(ContextFlags::ActiveDocumentIsWritable |
|
||||
ContextFlags::HasVisibleMask)) {
|
||||
Command* cmd = CommandsModule::instance()->getCommandByName(CommandId::DeselectMask);
|
||||
context->executeCommand(cmd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -212,8 +212,12 @@ void CanvasSizeCommand::onExecute(Context* context)
|
||||
Sprite* sprite = writer.sprite();
|
||||
UndoTransaction undoTransaction(writer.context(), "Canvas Size");
|
||||
DocumentApi api = document->getApi();
|
||||
int bgcolor = color_utils::color_for_image(context->getSettings()->getBgColor(), sprite->getPixelFormat());
|
||||
bgcolor = color_utils::fixup_color_for_background(sprite->getPixelFormat(), bgcolor);
|
||||
raster::color_t bgcolor = color_utils::color_for_target(
|
||||
context->getSettings()->getBgColor(),
|
||||
ColorTarget(
|
||||
ColorTarget::BackgroundLayer,
|
||||
sprite->getPixelFormat(),
|
||||
sprite->getTransparentColor()));
|
||||
|
||||
api.cropSprite(sprite, gfx::Rect(x1, y1, x2-x1, y2-y1), bgcolor);
|
||||
undoTransaction.commit();
|
||||
|
@ -23,11 +23,11 @@
|
||||
#include "app/app.h"
|
||||
#include "app/commands/command.h"
|
||||
#include "app/context_access.h"
|
||||
#include "app/document_api.h"
|
||||
#include "app/find_widget.h"
|
||||
#include "app/load_widget.h"
|
||||
#include "app/modules/gui.h"
|
||||
#include "app/undo_transaction.h"
|
||||
#include "app/undoers/set_cel_opacity.h"
|
||||
#include "base/mem_utils.h"
|
||||
#include "raster/cel.h"
|
||||
#include "raster/image.h"
|
||||
@ -129,22 +129,21 @@ void CelPropertiesCommand::onExecute(Context* context)
|
||||
if (window->getKiller() == button_ok) {
|
||||
ContextWriter writer(reader);
|
||||
Document* document_writer = writer.document();
|
||||
Sprite* sprite_writer = writer.sprite();
|
||||
Cel* cel_writer = writer.cel();
|
||||
|
||||
int new_opacity = slider_opacity->getValue();
|
||||
int newOpacity = slider_opacity->getValue();
|
||||
|
||||
// The opacity was changed?
|
||||
if (cel_writer != NULL &&
|
||||
cel_writer->getOpacity() != new_opacity) {
|
||||
UndoTransaction undo(writer.context(), "Cel Opacity Change", undo::ModifyDocument);
|
||||
if (undo.isEnabled()) {
|
||||
undo.pushUndoer(new undoers::SetCelOpacity(undo.getObjects(), cel_writer));
|
||||
cel_writer->getOpacity() != newOpacity) {
|
||||
DocumentApi api = document_writer->getApi();
|
||||
{
|
||||
UndoTransaction undo(writer.context(), "Cel Opacity Change", undo::ModifyDocument);
|
||||
api.setCelOpacity(sprite_writer, cel_writer, newOpacity);
|
||||
undo.commit();
|
||||
}
|
||||
|
||||
// Change cel opacity.
|
||||
cel_writer->setOpacity(new_opacity);
|
||||
|
||||
update_screen_for_document(document_writer);
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ void ClearCommand::onExecute(Context* context)
|
||||
{
|
||||
// Clear of several frames is handled with RemoveCel command.
|
||||
Timeline::Range range = App::instance()->getMainWindow()->getTimeline()->range();
|
||||
if (range.enabled()) {
|
||||
if (range.enabled() && (range.layers() > 1 || range.frames() > 1)) {
|
||||
Command* subCommand = CommandsModule::instance()
|
||||
->getCommandByName(CommandId::RemoveCel);
|
||||
context->executeCommand(subCommand);
|
||||
|
@ -20,10 +20,14 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/commands/command.h"
|
||||
#include "app/context.h"
|
||||
#include "app/document.h"
|
||||
#include "app/documents.h"
|
||||
#include "app/ui/devconsole_view.h"
|
||||
#include "app/ui/main_window.h"
|
||||
#include "app/ui/workspace.h"
|
||||
#include "ui/box.h"
|
||||
#include "ui/button.h"
|
||||
#include "ui/combobox.h"
|
||||
@ -33,36 +37,6 @@ namespace app {
|
||||
|
||||
using namespace ui;
|
||||
|
||||
class DeveloperConsole : public Window {
|
||||
public:
|
||||
DeveloperConsole()
|
||||
: Window(WithTitleBar, "Developer Console")
|
||||
, m_vbox(JI_VERTICAL)
|
||||
{
|
||||
m_vbox.addChild(&m_docs);
|
||||
addChild(&m_vbox);
|
||||
|
||||
remapWindow();
|
||||
centerWindow();
|
||||
}
|
||||
|
||||
void updateDocuments(Context* context)
|
||||
{
|
||||
m_docs.removeAllItems();
|
||||
m_docs.addItem("Documents");
|
||||
for (Documents::const_iterator
|
||||
it = context->getDocuments().begin(),
|
||||
end = context->getDocuments().end(); it != end; ++it) {
|
||||
m_docs.addItem((*it)->getFilename().c_str());
|
||||
}
|
||||
m_docs.addItem("---------");
|
||||
}
|
||||
|
||||
private:
|
||||
Box m_vbox;
|
||||
ComboBox m_docs;
|
||||
};
|
||||
|
||||
class DeveloperConsoleCommand : public Command {
|
||||
public:
|
||||
DeveloperConsoleCommand();
|
||||
@ -71,7 +45,7 @@ public:
|
||||
protected:
|
||||
void onExecute(Context* context);
|
||||
|
||||
DeveloperConsole* m_devConsole;
|
||||
DevConsoleView* m_devConsole;
|
||||
};
|
||||
|
||||
DeveloperConsoleCommand::DeveloperConsoleCommand()
|
||||
@ -84,21 +58,19 @@ DeveloperConsoleCommand::DeveloperConsoleCommand()
|
||||
|
||||
DeveloperConsoleCommand::~DeveloperConsoleCommand()
|
||||
{
|
||||
// delete m_devConsole;
|
||||
delete m_devConsole;
|
||||
}
|
||||
|
||||
void DeveloperConsoleCommand::onExecute(Context* context)
|
||||
{
|
||||
if (!m_devConsole) {
|
||||
m_devConsole = new DeveloperConsole();
|
||||
}
|
||||
else if (m_devConsole->isVisible()) {
|
||||
m_devConsole->closeWindow(NULL);
|
||||
return;
|
||||
m_devConsole = new DevConsoleView();
|
||||
|
||||
App::instance()->getMainWindow()->getWorkspace()->addView(m_devConsole);
|
||||
}
|
||||
|
||||
m_devConsole->updateDocuments(context);
|
||||
m_devConsole->openWindow();
|
||||
App::instance()->getMainWindow()->getTabsBar()->selectTab(m_devConsole);
|
||||
App::instance()->getMainWindow()->getWorkspace()->setActiveView(m_devConsole);
|
||||
}
|
||||
|
||||
Command* CommandFactory::createDeveloperConsoleCommand()
|
||||
|
@ -73,7 +73,7 @@ void DuplicateSpriteCommand::onExecute(Context* context)
|
||||
dst_name = window->findChild("dst_name");
|
||||
flatten = window->findChild("flatten");
|
||||
|
||||
base::string fn = document->getFilename();
|
||||
std::string fn = document->getFilename();
|
||||
src_name->setText(base::get_file_name(fn));
|
||||
dst_name->setText(base::get_file_title(fn) + " Copy." + base::get_file_extension(fn));
|
||||
|
||||
|
@ -92,7 +92,7 @@ public:
|
||||
hbox1->addChild(hbox2);
|
||||
hbox2->addChild(&m_export);
|
||||
hbox2->addChild(&m_cancel);
|
||||
jwidget_set_min_size(&m_export, 60, 0);
|
||||
m_export.setMinSize(gfx::Size(60, 0));
|
||||
m_grid.addChildInCell(hbox1, 4, 1, 0);
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,7 @@ void FlipCommand::onExecute(Context* context)
|
||||
|
||||
// If the mask isn't a rectangular area, we've to flip the mask too.
|
||||
if (mask->getBitmap() != NULL && !mask->isRectangular()) {
|
||||
int bgcolor = app_get_color_to_clear_layer(writer.layer());
|
||||
raster::color_t bgcolor = app_get_color_to_clear_layer(writer.layer());
|
||||
|
||||
// Flip the portion of image specified by the mask.
|
||||
mask->offsetOrigin(-x, -y);
|
||||
|
@ -90,7 +90,7 @@ public:
|
||||
hbox1->addChild(hbox2);
|
||||
hbox2->addChild(&m_import);
|
||||
hbox2->addChild(&m_cancel);
|
||||
jwidget_set_min_size(&m_import, 60, 0);
|
||||
m_import.setMinSize(gfx::Size(60, 0));
|
||||
m_grid.addChildInCell(hbox1, 4, 1, 0);
|
||||
}
|
||||
|
||||
|
@ -63,6 +63,10 @@ void LaunchCommand::onLoadParams(Params* params)
|
||||
m_type = Url;
|
||||
|
||||
m_path = params->get("path");
|
||||
|
||||
if (m_type == Url && !m_path.empty() && m_path[0] == '/') {
|
||||
m_path = WEBSITE + m_path.substr(1);
|
||||
}
|
||||
}
|
||||
|
||||
void LaunchCommand::onExecute(Context* context)
|
||||
|
@ -74,7 +74,7 @@ void LayerPropertiesCommand::onExecute(Context* context)
|
||||
button_ok->Click.connect(Bind<void>(&Window::closeWindow, window.get(), button_ok));
|
||||
button_cancel->Click.connect(Bind<void>(&Window::closeWindow, window.get(), button_cancel));
|
||||
|
||||
jwidget_set_min_size(entry_name, 128, 0);
|
||||
entry_name->setMinSize(gfx::Size(128, 0));
|
||||
entry_name->setExpansive(true);
|
||||
|
||||
box2->addChild(label_name);
|
||||
|
@ -70,7 +70,7 @@ void LoadMaskCommand::onExecute(Context* context)
|
||||
{
|
||||
const ContextReader reader(context);
|
||||
|
||||
base::string filename = m_filename;
|
||||
std::string filename = m_filename;
|
||||
|
||||
if (context->isUiAvailable()) {
|
||||
filename = app::show_file_selector("Load .msk File", filename, "msk");
|
||||
|
@ -52,7 +52,7 @@ LoadPaletteCommand::LoadPaletteCommand()
|
||||
|
||||
void LoadPaletteCommand::onExecute(Context* context)
|
||||
{
|
||||
base::string filename = app::show_file_selector("Load Palette", "", "png,pcx,bmp,tga,lbm,col,gpl");
|
||||
std::string filename = app::show_file_selector("Load Palette", "", "png,pcx,bmp,tga,lbm,col,gpl");
|
||||
if (!filename.empty()) {
|
||||
base::UniquePtr<raster::Palette> palette(raster::Palette::load(filename.c_str()));
|
||||
if (!palette) {
|
||||
|
@ -132,7 +132,7 @@ void MergeDownLayerCommand::onExecute(Context* context)
|
||||
}
|
||||
// With destination
|
||||
else {
|
||||
int x1, y1, x2, y2, bgcolor;
|
||||
int x1, y1, x2, y2;
|
||||
Image *new_image;
|
||||
|
||||
// Merge down in the background layer
|
||||
@ -141,7 +141,6 @@ void MergeDownLayerCommand::onExecute(Context* context)
|
||||
y1 = 0;
|
||||
x2 = sprite->getWidth();
|
||||
y2 = sprite->getHeight();
|
||||
bgcolor = app_get_color_to_clear_layer(dst_layer);
|
||||
}
|
||||
// Merge down in a transparent layer
|
||||
else {
|
||||
@ -149,9 +148,10 @@ void MergeDownLayerCommand::onExecute(Context* context)
|
||||
y1 = MIN(src_cel->getY(), dst_cel->getY());
|
||||
x2 = MAX(src_cel->getX()+src_image->getWidth()-1, dst_cel->getX()+dst_image->getWidth()-1);
|
||||
y2 = MAX(src_cel->getY()+src_image->getHeight()-1, dst_cel->getY()+dst_image->getHeight()-1);
|
||||
bgcolor = 0;
|
||||
}
|
||||
|
||||
raster::color_t bgcolor = app_get_color_to_clear_layer(dst_layer);
|
||||
|
||||
new_image = raster::crop_image(dst_image,
|
||||
x1-dst_cel->getX(),
|
||||
y1-dst_cel->getY(),
|
||||
|
@ -76,7 +76,7 @@ NewFileCommand::NewFileCommand()
|
||||
void NewFileCommand::onExecute(Context* context)
|
||||
{
|
||||
PixelFormat format;
|
||||
int w, h, bg, ncolors;
|
||||
int w, h, bg, ncolors = raster::Palette::MaxColors;
|
||||
char buf[1024];
|
||||
app::Color bg_table[] = {
|
||||
app::Color::fromMask(),
|
||||
@ -93,7 +93,7 @@ void NewFileCommand::onExecute(Context* context)
|
||||
Widget* radio1 = app::find_widget<Widget>(window, "radio1");
|
||||
Widget* radio2 = app::find_widget<Widget>(window, "radio2");
|
||||
Widget* radio3 = app::find_widget<Widget>(window, "radio3");
|
||||
Widget* colors = app::find_widget<Widget>(window, "colors");
|
||||
// Widget* colors = app::find_widget<Widget>(window, "colors");
|
||||
ListBox* bg_box = app::find_widget<ListBox>(window, "bg_box");
|
||||
Widget* ok = app::find_widget<Widget>(window, "ok_button");
|
||||
|
||||
@ -106,7 +106,7 @@ void NewFileCommand::onExecute(Context* context)
|
||||
w = get_config_int("NewSprite", "Width", 320);
|
||||
h = get_config_int("NewSprite", "Height", 240);
|
||||
bg = get_config_int("NewSprite", "Background", 4); // Default = Background color
|
||||
ncolors = get_config_int("NewSprite", "Colors", 256);
|
||||
// ncolors = get_config_int("NewSprite", "Colors", 256);
|
||||
|
||||
// If the clipboard contains an image, we can show the size of the
|
||||
// clipboard as default image size.
|
||||
@ -118,7 +118,7 @@ void NewFileCommand::onExecute(Context* context)
|
||||
|
||||
width->setTextf("%d", MAX(1, w));
|
||||
height->setTextf("%d", MAX(1, h));
|
||||
colors->setTextf("%d", MID(2, ncolors, 256));
|
||||
// colors->setTextf("%d", MID(2, ncolors, 256));
|
||||
|
||||
// Select image-type
|
||||
switch (format) {
|
||||
@ -143,7 +143,7 @@ void NewFileCommand::onExecute(Context* context)
|
||||
|
||||
w = width->getTextInt();
|
||||
h = height->getTextInt();
|
||||
ncolors = colors->getTextInt();
|
||||
// ncolors = colors->getTextInt();
|
||||
bg = bg_box->getSelectedIndex();
|
||||
|
||||
w = MID(1, w, 65535);
|
||||
@ -174,7 +174,8 @@ void NewFileCommand::onExecute(Context* context)
|
||||
(format == IMAGE_INDEXED ? ncolors: 256)));
|
||||
Sprite* sprite(document->getSprite());
|
||||
|
||||
get_default_palette()->copyColorsTo(sprite->getPalette(FrameNumber(0)));
|
||||
if (sprite->getPixelFormat() != IMAGE_GRAYSCALE)
|
||||
get_default_palette()->copyColorsTo(sprite->getPalette(FrameNumber(0)));
|
||||
|
||||
usprintf(buf, "Sprite-%04d", ++_sprite_counter);
|
||||
document->setFilename(buf);
|
||||
@ -190,7 +191,12 @@ void NewFileCommand::onExecute(Context* context)
|
||||
layerImage->configureAsBackground();
|
||||
|
||||
Image* image = sprite->getStock()->getImage(layerImage->getCel(FrameNumber(0))->getImage());
|
||||
raster::clear_image(image, color_utils::color_for_image(color, format));
|
||||
raster::clear_image(image,
|
||||
color_utils::color_for_target(color,
|
||||
ColorTarget(
|
||||
ColorTarget::BackgroundLayer,
|
||||
sprite->getPixelFormat(),
|
||||
sprite->getTransparentColor())));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,11 +60,7 @@ NewFrameCommand::NewFrameCommand()
|
||||
bool NewFrameCommand::onEnabled(Context* context)
|
||||
{
|
||||
return context->checkFlags(ContextFlags::ActiveDocumentIsWritable |
|
||||
ContextFlags::HasActiveSprite |
|
||||
ContextFlags::HasActiveLayer |
|
||||
ContextFlags::ActiveLayerIsReadable |
|
||||
ContextFlags::ActiveLayerIsWritable |
|
||||
ContextFlags::ActiveLayerIsImage);
|
||||
ContextFlags::HasActiveSprite);
|
||||
}
|
||||
|
||||
void NewFrameCommand::onExecute(Context* context)
|
||||
|
@ -101,7 +101,7 @@ void NewLayerCommand::onExecute(Context* context)
|
||||
base::UniquePtr<Window> window(app::load_widget<Window>("new_layer.xml", "new_layer"));
|
||||
Widget* name_widget = app::find_widget<Widget>(window, "name");
|
||||
name_widget->setText(name.c_str());
|
||||
jwidget_set_min_size(name_widget, 128, 0);
|
||||
name_widget->setMinSize(gfx::Size(128, 0));
|
||||
|
||||
window->openWindowInForeground();
|
||||
|
||||
|
67
src/app/commands/cmd_onionskin.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2014 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/commands/command.h"
|
||||
#include "app/context.h"
|
||||
#include "app/settings/document_settings.h"
|
||||
#include "app/settings/settings.h"
|
||||
#include "base/compiler_specific.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
using namespace ui;
|
||||
using namespace gfx;
|
||||
|
||||
class ShowOnionSkinCommand : public Command {
|
||||
public:
|
||||
ShowOnionSkinCommand()
|
||||
: Command("ShowOnionSkin",
|
||||
"Show Onion Skin",
|
||||
CmdUIOnlyFlag)
|
||||
{
|
||||
}
|
||||
|
||||
Command* clone() const OVERRIDE { return new ShowOnionSkinCommand(*this); }
|
||||
|
||||
protected:
|
||||
bool onChecked(Context* context)
|
||||
{
|
||||
IDocumentSettings* docSettings = context->getSettings()->getDocumentSettings(context->getActiveDocument());
|
||||
|
||||
return docSettings->getUseOnionskin();
|
||||
}
|
||||
|
||||
void onExecute(Context* context)
|
||||
{
|
||||
IDocumentSettings* docSettings = context->getSettings()->getDocumentSettings(context->getActiveDocument());
|
||||
|
||||
docSettings->setUseOnionskin(docSettings->getUseOnionskin() ? false: true);
|
||||
}
|
||||
};
|
||||
|
||||
Command* CommandFactory::createShowOnionSkinCommand()
|
||||
{
|
||||
return new ShowOnionSkinCommand;
|
||||
}
|
||||
|
||||
} // namespace app
|
@ -69,7 +69,11 @@ public:
|
||||
|
||||
void showProgressWindow() {
|
||||
startJob();
|
||||
fop_stop(m_fop);
|
||||
|
||||
if (isCanceled())
|
||||
fop_stop(m_fop);
|
||||
|
||||
waitJob();
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "app/commands/command.h"
|
||||
#include "app/context.h"
|
||||
#include "app/context_access.h"
|
||||
#include "app/handle_anidir.h"
|
||||
#include "app/modules/editors.h"
|
||||
#include "app/modules/gui.h"
|
||||
#include "app/modules/palettes.h"
|
||||
@ -87,6 +88,7 @@ void PlayAnimationCommand::onExecute(Context* context)
|
||||
IDocumentSettings* docSettings = context->getSettings()->getDocumentSettings(document);
|
||||
bool onionskin_state = docSettings->getUseOnionskin();
|
||||
Palette *oldpal, *newpal;
|
||||
bool pingPongForward = true;
|
||||
|
||||
if (sprite->getTotalFrames() < 2)
|
||||
return;
|
||||
@ -141,10 +143,12 @@ void PlayAnimationCommand::onExecute(Context* context)
|
||||
} while (!done && (speed_timer <= 0));
|
||||
|
||||
if (!done) {
|
||||
FrameNumber frame = current_editor->getFrame().next();
|
||||
if (frame > sprite->getLastFrame())
|
||||
frame = FrameNumber(0);
|
||||
current_editor->setFrame(frame);
|
||||
current_editor->setFrame(
|
||||
calculate_next_frame(
|
||||
sprite,
|
||||
current_editor->getFrame(),
|
||||
docSettings,
|
||||
pingPongForward));
|
||||
|
||||
speed_timer--;
|
||||
}
|
||||
|
@ -140,10 +140,13 @@ void PreviewCommand::onExecute(Context* context)
|
||||
// Render sprite and leave the result in 'render' variable
|
||||
if (render == NULL) {
|
||||
RenderEngine renderEngine(document, sprite,
|
||||
editor->getLayer(),
|
||||
editor->getFrame());
|
||||
render.reset(renderEngine.renderSprite(0, 0, sprite->getWidth(), sprite->getHeight(),
|
||||
editor->getFrame(), 0, false));
|
||||
editor->getLayer(),
|
||||
editor->getFrame());
|
||||
|
||||
render.reset(
|
||||
renderEngine.renderSprite(
|
||||
0, 0, sprite->getWidth(), sprite->getHeight(),
|
||||
editor->getFrame(), 0, false, false));
|
||||
}
|
||||
|
||||
// Redraw the screen
|
||||
|
@ -54,9 +54,11 @@ RemoveLayerCommand::RemoveLayerCommand()
|
||||
|
||||
bool RemoveLayerCommand::onEnabled(Context* context)
|
||||
{
|
||||
ContextWriter writer(context);
|
||||
Sprite* sprite(writer.sprite());
|
||||
return (sprite != NULL);
|
||||
return context->checkFlags(ContextFlags::ActiveDocumentIsWritable |
|
||||
ContextFlags::HasActiveSprite |
|
||||
ContextFlags::HasActiveLayer |
|
||||
ContextFlags::ActiveLayerIsReadable |
|
||||
ContextFlags::ActiveLayerIsWritable);
|
||||
}
|
||||
|
||||
void RemoveLayerCommand::onExecute(Context* context)
|
||||
|
@ -204,6 +204,7 @@ void RotateCanvasCommand::onExecute(Context* context)
|
||||
{
|
||||
RotateCanvasJob job(reader, m_angle);
|
||||
job.startJob();
|
||||
job.waitJob();
|
||||
}
|
||||
reader.document()->generateMaskBoundaries();
|
||||
update_screen_for_document(reader.document());
|
||||
|
@ -53,7 +53,12 @@ public:
|
||||
|
||||
void showProgressWindow() {
|
||||
startJob();
|
||||
fop_stop(m_fop);
|
||||
|
||||
if (isCanceled()) {
|
||||
fop_stop(m_fop);
|
||||
}
|
||||
|
||||
waitJob();
|
||||
}
|
||||
|
||||
private:
|
||||
@ -88,6 +93,14 @@ static void save_document_in_background(Document* document, bool mark_as_saved)
|
||||
if (fop->has_error()) {
|
||||
Console console;
|
||||
console.printf(fop->error.c_str());
|
||||
|
||||
// We don't know if the file was saved correctly or not. So mark
|
||||
// it as it should be saved again.
|
||||
document->impossibleToBackToSavedState();
|
||||
}
|
||||
// If the job was cancelled, mark the document as modified.
|
||||
else if (fop_is_stop(fop)) {
|
||||
document->impossibleToBackToSavedState();
|
||||
}
|
||||
else {
|
||||
App::instance()->getRecentFiles()->addRecentFile(document->getFilename().c_str());
|
||||
@ -122,7 +135,7 @@ protected:
|
||||
void saveAsDialog(const ContextReader& reader, const char* dlgTitle, bool markAsSaved)
|
||||
{
|
||||
const Document* document = reader.document();
|
||||
base::string filename;
|
||||
std::string filename;
|
||||
|
||||
if (!m_filename.empty()) {
|
||||
filename = m_filename;
|
||||
@ -134,7 +147,7 @@ protected:
|
||||
get_writable_extensions(exts, sizeof(exts));
|
||||
|
||||
for (;;) {
|
||||
base::string newfilename = app::show_file_selector(dlgTitle, filename, exts);
|
||||
std::string newfilename = app::show_file_selector(dlgTitle, filename, exts);
|
||||
if (newfilename.empty())
|
||||
return;
|
||||
|
||||
@ -283,7 +296,7 @@ void SaveFileCopyAsCommand::onExecute(Context* context)
|
||||
{
|
||||
const ContextReader reader(context);
|
||||
const Document* document(reader.document());
|
||||
base::string old_filename = document->getFilename();
|
||||
std::string old_filename = document->getFilename();
|
||||
|
||||
// show "Save As" dialog
|
||||
saveAsDialog(reader, "Save Copy As", false);
|
||||
|
@ -58,7 +58,7 @@ void SaveMaskCommand::onExecute(Context* context)
|
||||
{
|
||||
const ContextReader reader(context);
|
||||
const Document* document(reader.document());
|
||||
base::string filename = "default.msk";
|
||||
std::string filename = "default.msk";
|
||||
int ret;
|
||||
|
||||
for (;;) {
|
||||
|
@ -51,7 +51,7 @@ SavePaletteCommand::SavePaletteCommand()
|
||||
|
||||
void SavePaletteCommand::onExecute(Context* context)
|
||||
{
|
||||
base::string filename;
|
||||
std::string filename;
|
||||
int ret;
|
||||
|
||||
again:
|
||||
|
@ -23,10 +23,12 @@
|
||||
#include "app/color.h"
|
||||
#include "app/commands/command.h"
|
||||
#include "app/context_access.h"
|
||||
#include "app/document_api.h"
|
||||
#include "app/find_widget.h"
|
||||
#include "app/load_widget.h"
|
||||
#include "app/modules/gui.h"
|
||||
#include "app/ui/color_button.h"
|
||||
#include "app/undo_transaction.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/mem_utils.h"
|
||||
#include "raster/image.h"
|
||||
@ -67,7 +69,7 @@ bool SpritePropertiesCommand::onEnabled(Context* context)
|
||||
void SpritePropertiesCommand::onExecute(Context* context)
|
||||
{
|
||||
Widget* name, *type, *size, *frames, *ok, *box_transparent;
|
||||
base::string imgtype_text;
|
||||
std::string imgtype_text;
|
||||
char buf[256];
|
||||
ColorButton* color_button = NULL;
|
||||
|
||||
@ -148,8 +150,11 @@ void SpritePropertiesCommand::onExecute(Context* context)
|
||||
// property in the sprite.
|
||||
int index = color_button->getColor().getIndex();
|
||||
if (index != sprite->getTransparentColor()) {
|
||||
// TODO Add undo handling
|
||||
sprite->setTransparentColor(color_button->getColor().getIndex());
|
||||
UndoTransaction undoTransaction(writer.context(), "Set Transparent Color");
|
||||
DocumentApi api = writer.document()->getApi();
|
||||
api.setSpriteTransparentColor(sprite, index);
|
||||
undoTransaction.commit();
|
||||
|
||||
update_screen_for_document(writer.document());
|
||||
}
|
||||
}
|
||||
|
@ -243,6 +243,7 @@ void SpriteSizeCommand::onExecute(Context* context)
|
||||
{
|
||||
SpriteSizeJob job(reader, new_width, new_height, resize_method);
|
||||
job.startJob();
|
||||
job.waitJob();
|
||||
}
|
||||
|
||||
ContextWriter writer(reader);
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "app/ini_file.h"
|
||||
#include "app/modules/editors.h"
|
||||
#include "app/modules/gui.h"
|
||||
#include "app/modules/palettes.h"
|
||||
#include "app/ui/editor/editor.h"
|
||||
#include "app/ui/status_bar.h"
|
||||
#include "base/thread.h"
|
||||
@ -117,6 +118,7 @@ void UndoCommand::onExecute(Context* context)
|
||||
document->destroyExtraCel(); // Regenerate extras
|
||||
|
||||
update_screen_for_document(document);
|
||||
set_current_palette(writer.palette(), false);
|
||||
}
|
||||
|
||||
Command* CommandFactory::createUndoCommand()
|
||||
|
@ -99,6 +99,7 @@ FOR_EACH_COMMAND(SavePalette)
|
||||
FOR_EACH_COMMAND(Scroll)
|
||||
FOR_EACH_COMMAND(SetPalette)
|
||||
FOR_EACH_COMMAND(ShowGrid)
|
||||
FOR_EACH_COMMAND(ShowOnionSkin)
|
||||
FOR_EACH_COMMAND(SnapToGrid)
|
||||
FOR_EACH_COMMAND(SplitEditorHorizontally)
|
||||
FOR_EACH_COMMAND(SplitEditorVertically)
|
||||
|
@ -60,7 +60,7 @@ public:
|
||||
{
|
||||
m_view.attachToView(&m_editor);
|
||||
m_view.setExpansive(true);
|
||||
jwidget_set_min_size(&m_view, 128, 64);
|
||||
m_view.setMinSize(gfx::Size(128, 64));
|
||||
|
||||
getContainer()->addChild(&m_view);
|
||||
|
||||
|
@ -68,7 +68,7 @@ Console::Console()
|
||||
|
||||
view->attachToView(textbox);
|
||||
|
||||
jwidget_set_min_size(button, 60, 0);
|
||||
button->setMinSize(gfx::Size(60, 0));
|
||||
|
||||
grid->addChildInCell(view, 1, 1, JI_HORIZONTAL | JI_VERTICAL);
|
||||
grid->addChildInCell(button, 1, 1, JI_CENTER);
|
||||
@ -138,7 +138,7 @@ void Console::printf(const char* format, ...)
|
||||
|
||||
const std::string& text = wid_textbox->getText();
|
||||
|
||||
base::string final;
|
||||
std::string final;
|
||||
if (!text.empty())
|
||||
final += text;
|
||||
final += buf;
|
||||
|
@ -51,6 +51,10 @@ namespace app {
|
||||
return m_location.image(x, y, opacity);
|
||||
}
|
||||
|
||||
Palette* palette() const {
|
||||
return m_location.palette();
|
||||
}
|
||||
|
||||
protected:
|
||||
ContextAccess(const Context* context)
|
||||
: m_context(context)
|
||||
|
@ -39,7 +39,7 @@ DataRecovery::DataRecovery(Context* context)
|
||||
, m_context(context)
|
||||
{
|
||||
// Check if there is already data to recover
|
||||
const base::string existent_data_path = get_config_string("DataRecovery", "Path", "");
|
||||
const std::string existent_data_path = get_config_string("DataRecovery", "Path", "");
|
||||
if (!existent_data_path.empty() &&
|
||||
base::is_directory(existent_data_path)) {
|
||||
// Load the backup data.
|
||||
|
@ -189,7 +189,7 @@ void Document::notifyCelCopied(Layer* fromLayer, FrameNumber fromFrame, Layer* t
|
||||
notifyObservers<DocumentEvent&>(&DocumentObserver::onCelCopied, ev);
|
||||
}
|
||||
|
||||
void Document::setFilename(const base::string& filename)
|
||||
void Document::setFilename(const std::string& filename)
|
||||
{
|
||||
m_document.setFilename(filename);
|
||||
}
|
||||
@ -210,6 +210,11 @@ void Document::markAsSaved()
|
||||
m_associated_to_file = true;
|
||||
}
|
||||
|
||||
void Document::impossibleToBackToSavedState()
|
||||
{
|
||||
m_undo->impossibleToBackToSavedState();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Loaded options from file
|
||||
|
||||
@ -290,8 +295,6 @@ void Document::prepareExtraCel(int x, int y, int w, int h, int opacity)
|
||||
m_extraImage->getHeight() != h) {
|
||||
delete m_extraImage; // image
|
||||
m_extraImage = Image::create(getSprite()->getPixelFormat(), w, h);
|
||||
m_extraImage->setMaskColor(0);
|
||||
clear_image(m_extraImage, m_extraImage->getMaskColor());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,13 +24,14 @@
|
||||
#include "base/disable_copying.h"
|
||||
#include "base/observable.h"
|
||||
#include "base/shared_ptr.h"
|
||||
#include "base/string.h"
|
||||
#include "base/unique_ptr.h"
|
||||
#include "doc/document.h"
|
||||
#include "gfx/transformation.h"
|
||||
#include "raster/frame_number.h"
|
||||
#include "raster/pixel_format.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace base {
|
||||
class mutex;
|
||||
}
|
||||
@ -122,13 +123,19 @@ namespace app {
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// File related properties
|
||||
|
||||
const base::string& getFilename() const { return m_document.filename(); }
|
||||
void setFilename(const base::string& filename);
|
||||
const std::string& getFilename() const { return m_document.filename(); }
|
||||
void setFilename(const std::string& filename);
|
||||
|
||||
bool isModified() const;
|
||||
bool isAssociatedToFile() const;
|
||||
void markAsSaved();
|
||||
|
||||
// You can use this to indicate that we've destroyed (or we cannot
|
||||
// trust) the file associated with the document (e.g. when we
|
||||
// cancel a Save operation in the middle). So it's impossible to
|
||||
// back to the saved state using the UndoHistory.
|
||||
void impossibleToBackToSavedState();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Loaded options from file
|
||||
|
||||
|
@ -55,6 +55,7 @@
|
||||
#include "app/undoers/set_palette_colors.h"
|
||||
#include "app/undoers/set_sprite_pixel_format.h"
|
||||
#include "app/undoers/set_sprite_size.h"
|
||||
#include "app/undoers/set_sprite_transparent_color.h"
|
||||
#include "app/undoers/set_stock_pixel_format.h"
|
||||
#include "app/undoers/set_total_frames.h"
|
||||
#include "base/unique_ptr.h"
|
||||
@ -100,6 +101,18 @@ void DocumentApi::setSpriteSize(Sprite* sprite, int w, int h)
|
||||
m_document->notifyObservers<DocumentEvent&>(&DocumentObserver::onSpriteSizeChanged, ev);
|
||||
}
|
||||
|
||||
void DocumentApi::setSpriteTransparentColor(Sprite* sprite, color_t maskColor)
|
||||
{
|
||||
if (undoEnabled())
|
||||
m_undoers->pushUndoer(new undoers::SetSpriteTransparentColor(getObjects(), sprite));
|
||||
|
||||
sprite->setTransparentColor(maskColor);
|
||||
|
||||
DocumentEvent ev(m_document);
|
||||
ev.sprite(sprite);
|
||||
m_document->notifyObservers<DocumentEvent&>(&DocumentObserver::onSpriteTransparentColorChanged, ev);
|
||||
}
|
||||
|
||||
void DocumentApi::cropSprite(Sprite* sprite, const gfx::Rect& bounds, color_t bgcolor)
|
||||
{
|
||||
setSpriteSize(sprite, bounds.w, bounds.h);
|
||||
@ -160,15 +173,30 @@ void DocumentApi::setPixelFormat(Sprite* sprite, PixelFormat newFormat, Ditherin
|
||||
// Use the rgbmap for the specified sprite
|
||||
const RgbMap* rgbmap = sprite->getRgbMap(frame);
|
||||
|
||||
// Get the list of cels from the background layer (if it
|
||||
// exists). This list will be used to check if each image belong to
|
||||
// the background layer.
|
||||
CelList bgCels;
|
||||
if (sprite->getBackgroundLayer() != NULL)
|
||||
sprite->getBackgroundLayer()->getCels(bgCels);
|
||||
|
||||
for (c=0; c<sprite->getStock()->size(); c++) {
|
||||
old_image = sprite->getStock()->getImage(c);
|
||||
if (!old_image)
|
||||
continue;
|
||||
|
||||
bool is_image_from_background = false;
|
||||
for (CelList::iterator it=bgCels.begin(), end=bgCels.end(); it != end; ++it) {
|
||||
if ((*it)->getImage() == c) {
|
||||
is_image_from_background = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
new_image = quantization::convert_pixel_format
|
||||
(old_image, newFormat, dithering_method, rgbmap,
|
||||
sprite->getPalette(frame),
|
||||
sprite->getBackgroundLayer() != NULL);
|
||||
is_image_from_background);
|
||||
|
||||
replaceStockImage(sprite, c, new_image);
|
||||
}
|
||||
@ -498,20 +526,13 @@ void DocumentApi::removeCel(LayerImage* layer, Cel* cel)
|
||||
ev.cel(cel);
|
||||
m_document->notifyObservers<DocumentEvent&>(&DocumentObserver::onRemoveCel, ev);
|
||||
|
||||
// Find if the image that use the cel to remove, is used by another
|
||||
// cels.
|
||||
bool used = false;
|
||||
for (FrameNumber frame(0); frame<sprite->getTotalFrames(); ++frame) {
|
||||
Cel* it = layer->getCel(frame);
|
||||
if (it && it != cel && it->getImage() == cel->getImage()) {
|
||||
used = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Find if the image that use this cel we are going to remove, is
|
||||
// used by other cels.
|
||||
size_t refs = sprite->getImageRefs(cel->getImage());
|
||||
|
||||
// If the image is only used by this cel, we can remove the image
|
||||
// from the stock.
|
||||
if (!used)
|
||||
if (refs == 1)
|
||||
removeImageFromStock(sprite, cel->getImage());
|
||||
|
||||
if (undoEnabled())
|
||||
@ -558,6 +579,21 @@ void DocumentApi::setCelPosition(Sprite* sprite, Cel* cel, int x, int y)
|
||||
m_document->notifyObservers<DocumentEvent&>(&DocumentObserver::onCelPositionChanged, ev);
|
||||
}
|
||||
|
||||
void DocumentApi::setCelOpacity(Sprite* sprite, Cel* cel, int newOpacity)
|
||||
{
|
||||
ASSERT(cel);
|
||||
|
||||
if (undoEnabled())
|
||||
m_undoers->pushUndoer(new undoers::SetCelOpacity(getObjects(), cel));
|
||||
|
||||
cel->setOpacity(newOpacity);
|
||||
|
||||
DocumentEvent ev(m_document);
|
||||
ev.sprite(sprite);
|
||||
ev.cel(cel);
|
||||
m_document->notifyObservers<DocumentEvent&>(&DocumentObserver::onCelOpacityChanged, ev);
|
||||
}
|
||||
|
||||
void DocumentApi::cropCel(Sprite* sprite, Cel* cel, int x, int y, int w, int h, color_t bgcolor)
|
||||
{
|
||||
Image* cel_image = sprite->getStock()->getImage(cel->getImage());
|
||||
@ -583,16 +619,17 @@ void DocumentApi::moveCel(Sprite* sprite,
|
||||
ASSERT(srcFrame >= 0 && srcFrame < sprite->getTotalFrames());
|
||||
ASSERT(dstFrame >= 0 && dstFrame < sprite->getTotalFrames());
|
||||
|
||||
// Background to any other layer, we use copyCel() instead.
|
||||
if (srcLayer->isBackground()) {
|
||||
copyCel(sprite, srcLayer, dstLayer, srcFrame, dstFrame, bgcolor);
|
||||
return;
|
||||
}
|
||||
|
||||
Cel* srcCel = srcLayer->getCel(srcFrame);
|
||||
Cel* dstCel = dstLayer->getCel(dstFrame);
|
||||
// In this we copy from a transparent layer to another layer...
|
||||
|
||||
// Remove the dstCel (if it exists) because it must be replaced with
|
||||
// srcCel.
|
||||
Cel* srcCel = srcLayer->getCel(srcFrame);
|
||||
Cel* dstCel = dstLayer->getCel(dstFrame);
|
||||
if ((dstCel != NULL) && (!dstLayer->isBackground() || srcCel != NULL))
|
||||
removeCel(dstLayer, dstCel);
|
||||
|
||||
@ -603,17 +640,14 @@ void DocumentApi::moveCel(Sprite* sprite,
|
||||
}
|
||||
// Move the cel between different layers.
|
||||
else {
|
||||
if (undoEnabled())
|
||||
m_undoers->pushUndoer(new undoers::RemoveCel(getObjects(), srcLayer, srcCel));
|
||||
srcLayer->removeCel(srcCel);
|
||||
|
||||
srcCel->setFrame(dstFrame);
|
||||
Cel* newCel = new Cel(*srcCel);
|
||||
newCel->setFrame(dstFrame);
|
||||
|
||||
// If we are moving a cel from a transparent layer to the
|
||||
// background layer, we have to clear the background of the
|
||||
// image.
|
||||
if (!srcLayer->isBackground() &&
|
||||
dstLayer->isBackground()) {
|
||||
ASSERT(!srcLayer->isBackground());
|
||||
if (dstLayer->isBackground()) {
|
||||
Image* srcImage = sprite->getStock()->getImage(srcCel->getImage());
|
||||
Image* dstImage = crop_image(srcImage,
|
||||
-srcCel->getX(),
|
||||
@ -621,24 +655,17 @@ void DocumentApi::moveCel(Sprite* sprite,
|
||||
sprite->getWidth(),
|
||||
sprite->getHeight(), 0);
|
||||
|
||||
if (undoEnabled()) {
|
||||
m_undoers->pushUndoer(new undoers::ReplaceImage(getObjects(),
|
||||
sprite->getStock(), srcCel->getImage()));
|
||||
m_undoers->pushUndoer(new undoers::SetCelPosition(getObjects(), srcCel));
|
||||
m_undoers->pushUndoer(new undoers::SetCelOpacity(getObjects(), srcCel));
|
||||
}
|
||||
|
||||
clear_image(dstImage, bgcolor);
|
||||
composite_image(dstImage, srcImage, srcCel->getX(), srcCel->getY(), 255, BLEND_MODE_NORMAL);
|
||||
|
||||
srcCel->setPosition(0, 0);
|
||||
srcCel->setOpacity(255);
|
||||
|
||||
sprite->getStock()->replaceImage(srcCel->getImage(), dstImage);
|
||||
delete srcImage;
|
||||
newCel->setPosition(0, 0);
|
||||
newCel->setOpacity(255);
|
||||
newCel->setImage(addImageInStock(sprite, dstImage));
|
||||
}
|
||||
|
||||
addCel(dstLayer, srcCel);
|
||||
// Add and the remove, so the Stock's image is reused.
|
||||
addCel(dstLayer, newCel);
|
||||
removeCel(srcLayer, srcCel);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,6 +62,7 @@ namespace app {
|
||||
|
||||
// Sprite API
|
||||
void setSpriteSize(Sprite* sprite, int w, int h);
|
||||
void setSpriteTransparentColor(Sprite* sprite, color_t maskColor);
|
||||
void cropSprite(Sprite* sprite, const gfx::Rect& bounds, color_t bgcolor);
|
||||
void trimSprite(Sprite* sprite, color_t bgcolor);
|
||||
void setPixelFormat(Sprite* sprite, PixelFormat newFormat, DitheringMethod dithering_method);
|
||||
@ -79,6 +80,7 @@ namespace app {
|
||||
void addCel(LayerImage* layer, Cel* cel);
|
||||
void removeCel(LayerImage* layer, Cel* cel);
|
||||
void setCelPosition(Sprite* sprite, Cel* cel, int x, int y);
|
||||
void setCelOpacity(Sprite* sprite, Cel* cel, int newOpacity);
|
||||
void cropCel(Sprite* sprite, Cel* cel, int x, int y, int w, int h, color_t bgcolor);
|
||||
void moveCel(Sprite* sprite,
|
||||
LayerImage* srcLayer, LayerImage* dstLayer,
|
||||
|
@ -194,18 +194,18 @@ void DocumentExporter::captureSamples(Samples& samples)
|
||||
|
||||
for (FrameNumber frame=FrameNumber(0);
|
||||
frame<sprite->getTotalFrames(); ++frame) {
|
||||
base::string filename = document->getFilename();
|
||||
std::string filename = document->getFilename();
|
||||
|
||||
if (sprite->getTotalFrames() > FrameNumber(1)) {
|
||||
int frameNumWidth =
|
||||
(sprite->getTotalFrames() < 10)? 1:
|
||||
(sprite->getTotalFrames() < 100)? 2:
|
||||
(sprite->getTotalFrames() < 1000)? 3: 4;
|
||||
std::sprintf(&buf[0], "%0*d", frameNumWidth, frame);
|
||||
std::sprintf(&buf[0], "%0*d", frameNumWidth, (int)frame);
|
||||
|
||||
base::string path = base::get_file_path(filename);
|
||||
base::string title = base::get_file_title(filename);
|
||||
base::string ext = base::get_file_extension(filename);
|
||||
std::string path = base::get_file_path(filename);
|
||||
std::string title = base::get_file_title(filename);
|
||||
std::string ext = base::get_file_extension(filename);
|
||||
filename = base::join_path(path, title + &buf[0] + "." + ext);
|
||||
}
|
||||
|
||||
|
@ -84,4 +84,9 @@ Image* DocumentLocation::image(int* x, int* y, int* opacity) const
|
||||
return image;
|
||||
}
|
||||
|
||||
Palette* DocumentLocation::palette() const
|
||||
{
|
||||
return (m_sprite ? m_sprite->getPalette(m_frame): NULL);
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -67,6 +67,7 @@ namespace app {
|
||||
void layerIndex(LayerIndex layerIndex);
|
||||
Palette* palette();
|
||||
Image* image(int* x = NULL, int* y = NULL, int* opacity = NULL) const;
|
||||
Palette* palette() const;
|
||||
|
||||
private:
|
||||
Document* m_document;
|
||||
|
@ -52,6 +52,7 @@ namespace app {
|
||||
virtual void onRemoveCel(DocumentEvent& ev) { }
|
||||
|
||||
virtual void onSpriteSizeChanged(DocumentEvent& ev) { }
|
||||
virtual void onSpriteTransparentColorChanged(DocumentEvent& ev) { }
|
||||
|
||||
virtual void onLayerRestacked(DocumentEvent& ev) { }
|
||||
virtual void onLayerMergedDown(DocumentEvent& ev) { }
|
||||
|
@ -74,6 +74,11 @@ void DocumentUndo::markSavedState()
|
||||
return m_undoHistory->markSavedState();
|
||||
}
|
||||
|
||||
void DocumentUndo::impossibleToBackToSavedState()
|
||||
{
|
||||
m_undoHistory->impossibleToBackToSavedState();
|
||||
}
|
||||
|
||||
void DocumentUndo::pushUndoer(undo::Undoer* undoer)
|
||||
{
|
||||
return m_undoHistory->pushUndoer(undoer);
|
||||
|
@ -55,6 +55,7 @@ namespace app {
|
||||
|
||||
bool isSavedState() const;
|
||||
void markSavedState();
|
||||
void impossibleToBackToSavedState();
|
||||
|
||||
// UndoHistoryDelegate implementation.
|
||||
undo::ObjectsContainer* getObjects() const OVERRIDE { return m_objects; }
|
||||
|
@ -75,39 +75,55 @@ struct ASE_FrameHeader {
|
||||
uint16_t duration;
|
||||
};
|
||||
|
||||
// TODO Warning: the writing routines aren't thread-safe
|
||||
static ASE_FrameHeader *current_frame_header = NULL;
|
||||
static int chunk_type;
|
||||
static int chunk_start;
|
||||
struct ASE_Chunk {
|
||||
int type;
|
||||
int start;
|
||||
};
|
||||
|
||||
static bool ase_file_read_header(FILE* f, ASE_Header* header);
|
||||
static void ase_file_prepare_header(FILE* f, ASE_Header* header, const Sprite* sprite);
|
||||
static void ase_file_write_header(FILE* f, ASE_Header* header);
|
||||
static void ase_file_write_header_filesize(FILE* f, ASE_Header* header);
|
||||
|
||||
static void ase_file_read_frame_header(FILE *f, ASE_FrameHeader *frame_header);
|
||||
static void ase_file_prepare_frame_header(FILE *f, ASE_FrameHeader *frame_header);
|
||||
static void ase_file_write_frame_header(FILE *f, ASE_FrameHeader *frame_header);
|
||||
static void ase_file_read_frame_header(FILE* f, ASE_FrameHeader* frame_header);
|
||||
static void ase_file_prepare_frame_header(FILE* f, ASE_FrameHeader* frame_header);
|
||||
static void ase_file_write_frame_header(FILE* f, ASE_FrameHeader* frame_header);
|
||||
|
||||
static void ase_file_write_layers(FILE *f, Layer *layer);
|
||||
static void ase_file_write_cels(FILE *f, Sprite *sprite, Layer *layer, FrameNumber frame);
|
||||
static void ase_file_write_layers(FILE* f, ASE_FrameHeader* frame_header, Layer* layer);
|
||||
static void ase_file_write_cels(FILE* f, ASE_FrameHeader* frame_header, Sprite* sprite, Layer* layer, FrameNumber frame);
|
||||
|
||||
static void ase_file_read_padding(FILE *f, int bytes);
|
||||
static void ase_file_write_padding(FILE *f, int bytes);
|
||||
static std::string ase_file_read_string(FILE *f);
|
||||
static void ase_file_write_string(FILE *f, const std::string& string);
|
||||
static void ase_file_read_padding(FILE* f, int bytes);
|
||||
static void ase_file_write_padding(FILE* f, int bytes);
|
||||
static std::string ase_file_read_string(FILE* f);
|
||||
static void ase_file_write_string(FILE* f, const std::string& string);
|
||||
|
||||
static void ase_file_write_start_chunk(FILE *f, int type);
|
||||
static void ase_file_write_close_chunk(FILE *f);
|
||||
static void ase_file_write_start_chunk(FILE* f, ASE_FrameHeader* frame_header, int type, ASE_Chunk* chunk);
|
||||
static void ase_file_write_close_chunk(FILE* f, ASE_Chunk* chunk);
|
||||
|
||||
static Palette *ase_file_read_color_chunk(FILE *f, Sprite *sprite, FrameNumber frame);
|
||||
static Palette *ase_file_read_color2_chunk(FILE *f, Sprite *sprite, FrameNumber frame);
|
||||
static void ase_file_write_color2_chunk(FILE *f, Palette *pal);
|
||||
static Layer *ase_file_read_layer_chunk(FILE *f, Sprite *sprite, Layer **previous_layer, int *current_level);
|
||||
static void ase_file_write_layer_chunk(FILE *f, Layer *layer);
|
||||
static Cel *ase_file_read_cel_chunk(FILE *f, Sprite *sprite, FrameNumber frame, PixelFormat pixelFormat, FileOp *fop, ASE_Header *header, size_t chunk_end);
|
||||
static void ase_file_write_cel_chunk(FILE *f, Cel *cel, LayerImage *layer, Sprite *sprite);
|
||||
static Mask *ase_file_read_mask_chunk(FILE *f);
|
||||
static void ase_file_write_mask_chunk(FILE *f, Mask *mask);
|
||||
static Palette* ase_file_read_color_chunk(FILE* f, Sprite* sprite, FrameNumber frame);
|
||||
static Palette* ase_file_read_color2_chunk(FILE* f, Sprite* sprite, FrameNumber frame);
|
||||
static void ase_file_write_color2_chunk(FILE* f, ASE_FrameHeader* frame_header, Palette* pal);
|
||||
static Layer* ase_file_read_layer_chunk(FILE* f, Sprite* sprite, Layer** previous_layer, int* current_level);
|
||||
static void ase_file_write_layer_chunk(FILE* f, ASE_FrameHeader* frame_header, Layer* layer);
|
||||
static Cel* ase_file_read_cel_chunk(FILE* f, Sprite* sprite, FrameNumber frame, PixelFormat pixelFormat, FileOp* fop, ASE_Header* header, size_t chunk_end);
|
||||
static void ase_file_write_cel_chunk(FILE* f, ASE_FrameHeader* frame_header, Cel* cel, LayerImage* layer, Sprite* sprite);
|
||||
static Mask* ase_file_read_mask_chunk(FILE* f);
|
||||
static void ase_file_write_mask_chunk(FILE* f, ASE_FrameHeader* frame_header, Mask* mask);
|
||||
|
||||
class ChunkWriter {
|
||||
public:
|
||||
ChunkWriter(FILE* f, ASE_FrameHeader* frame_header, int type) : m_file(f) {
|
||||
ase_file_write_start_chunk(m_file, frame_header, type, &m_chunk);
|
||||
}
|
||||
|
||||
~ChunkWriter() {
|
||||
ase_file_write_close_chunk(m_file, &m_chunk);
|
||||
}
|
||||
|
||||
private:
|
||||
FILE* m_file;
|
||||
ASE_Chunk m_chunk;
|
||||
};
|
||||
|
||||
class AseFormat : public FileFormat {
|
||||
const char* onGetName() const { return "ase"; }
|
||||
@ -137,7 +153,7 @@ FileFormat* CreateAseFormat()
|
||||
return new AseFormat;
|
||||
}
|
||||
|
||||
bool AseFormat::onLoad(FileOp *fop)
|
||||
bool AseFormat::onLoad(FileOp* fop)
|
||||
{
|
||||
FileHandle f(open_file_with_exception(fop->filename, "rb"));
|
||||
|
||||
@ -148,7 +164,7 @@ bool AseFormat::onLoad(FileOp *fop)
|
||||
}
|
||||
|
||||
// Create the new sprite
|
||||
Sprite *sprite = new Sprite(header.depth == 32 ? IMAGE_RGB:
|
||||
Sprite* sprite = new Sprite(header.depth == 32 ? IMAGE_RGB:
|
||||
header.depth == 16 ? IMAGE_GRAYSCALE: IMAGE_INDEXED,
|
||||
header.width, header.height, header.ncolors);
|
||||
if (!sprite) {
|
||||
@ -236,7 +252,7 @@ bool AseFormat::onLoad(FileOp *fop)
|
||||
}
|
||||
|
||||
case ASE_FILE_CHUNK_MASK: {
|
||||
Mask *mask;
|
||||
Mask* mask;
|
||||
|
||||
/* fop_error(fop, "Mask chunk\n"); */
|
||||
|
||||
@ -286,56 +302,59 @@ bool AseFormat::onLoad(FileOp *fop)
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SAVE
|
||||
bool AseFormat::onSave(FileOp *fop)
|
||||
bool AseFormat::onSave(FileOp* fop)
|
||||
{
|
||||
Sprite* sprite = fop->document->getSprite();
|
||||
ASE_Header header;
|
||||
ASE_FrameHeader frame_header;
|
||||
|
||||
FileHandle f(open_file_with_exception(fop->filename, "wb"));
|
||||
|
||||
/* prepare the header */
|
||||
// Write the header
|
||||
ASE_Header header;
|
||||
ase_file_prepare_header(f, &header, sprite);
|
||||
ase_file_write_header(f, &header);
|
||||
|
||||
/* write frame */
|
||||
// Write frames
|
||||
for (FrameNumber frame(0); frame<sprite->getTotalFrames(); ++frame) {
|
||||
/* prepare the header */
|
||||
// Prepare the frame header
|
||||
ASE_FrameHeader frame_header;
|
||||
ase_file_prepare_frame_header(f, &frame_header);
|
||||
|
||||
/* frame duration */
|
||||
// Frame duration
|
||||
frame_header.duration = sprite->getFrameDuration(frame);
|
||||
|
||||
/* the sprite is indexed and the palette changes? (or is the first frame) */
|
||||
// The sprite is indexed and the palette changes? (or is the first frame)
|
||||
if (sprite->getPixelFormat() == IMAGE_INDEXED &&
|
||||
(frame == 0 ||
|
||||
sprite->getPalette(frame.previous())->countDiff(sprite->getPalette(frame), NULL, NULL) > 0)) {
|
||||
/* write the color chunk */
|
||||
ase_file_write_color2_chunk(f, sprite->getPalette(frame));
|
||||
// Write the color chunk
|
||||
ase_file_write_color2_chunk(f, &frame_header, sprite->getPalette(frame));
|
||||
}
|
||||
|
||||
/* write extra chunks in the first frame */
|
||||
// Write extra chunks in the first frame
|
||||
if (frame == 0) {
|
||||
LayerIterator it = sprite->getFolder()->getLayerBegin();
|
||||
LayerIterator end = sprite->getFolder()->getLayerEnd();
|
||||
|
||||
/* write layer chunks */
|
||||
// Write layer chunks
|
||||
for (; it != end; ++it)
|
||||
ase_file_write_layers(f, *it);
|
||||
ase_file_write_layers(f, &frame_header, *it);
|
||||
}
|
||||
|
||||
/* write cel chunks */
|
||||
ase_file_write_cels(f, sprite, sprite->getFolder(), frame);
|
||||
// Write cel chunks
|
||||
ase_file_write_cels(f, &frame_header, sprite, sprite->getFolder(), frame);
|
||||
|
||||
/* write the frame header */
|
||||
// Write the frame header
|
||||
ase_file_write_frame_header(f, &frame_header);
|
||||
|
||||
/* progress */
|
||||
// Progress
|
||||
if (sprite->getTotalFrames() > 1)
|
||||
fop_progress(fop, (float)(frame.next()) / (float)(sprite->getTotalFrames()));
|
||||
|
||||
if (fop_is_stop(fop))
|
||||
break;
|
||||
}
|
||||
|
||||
/* write the header */
|
||||
ase_file_write_header(f, &header);
|
||||
// Write the missing field (filesize) of the header.
|
||||
ase_file_write_header_filesize(f, &header);
|
||||
|
||||
if (ferror(f)) {
|
||||
fop_error(fop, "Error writing file.\n");
|
||||
@ -347,7 +366,7 @@ bool AseFormat::onSave(FileOp *fop)
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool ase_file_read_header(FILE *f, ASE_Header *header)
|
||||
static bool ase_file_read_header(FILE* f, ASE_Header* header)
|
||||
{
|
||||
header->pos = ftell(f);
|
||||
|
||||
@ -376,7 +395,7 @@ static bool ase_file_read_header(FILE *f, ASE_Header *header)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ase_file_prepare_header(FILE *f, ASE_Header *header, const Sprite* sprite)
|
||||
static void ase_file_prepare_header(FILE* f, ASE_Header* header, const Sprite* sprite)
|
||||
{
|
||||
header->pos = ftell(f);
|
||||
|
||||
@ -397,14 +416,10 @@ static void ase_file_prepare_header(FILE *f, ASE_Header *header, const Sprite* s
|
||||
header->ignore[1] = 0;
|
||||
header->ignore[2] = 0;
|
||||
header->ncolors = sprite->getPalette(FrameNumber(0))->size();
|
||||
|
||||
fseek(f, header->pos+128, SEEK_SET);
|
||||
}
|
||||
|
||||
static void ase_file_write_header(FILE *f, ASE_Header *header)
|
||||
static void ase_file_write_header(FILE* f, ASE_Header* header)
|
||||
{
|
||||
header->size = ftell(f)-header->pos;
|
||||
|
||||
fseek(f, header->pos, SEEK_SET);
|
||||
|
||||
fputl(header->size, f);
|
||||
@ -423,10 +438,20 @@ static void ase_file_write_header(FILE *f, ASE_Header *header)
|
||||
fputc(header->ignore[2], f);
|
||||
fputw(header->ncolors, f);
|
||||
|
||||
fseek(f, header->pos+128, SEEK_SET);
|
||||
}
|
||||
|
||||
static void ase_file_write_header_filesize(FILE* f, ASE_Header* header)
|
||||
{
|
||||
header->size = ftell(f)-header->pos;
|
||||
|
||||
fseek(f, header->pos, SEEK_SET);
|
||||
fputl(header->size, f);
|
||||
|
||||
fseek(f, header->pos+header->size, SEEK_SET);
|
||||
}
|
||||
|
||||
static void ase_file_read_frame_header(FILE *f, ASE_FrameHeader *frame_header)
|
||||
static void ase_file_read_frame_header(FILE* f, ASE_FrameHeader* frame_header)
|
||||
{
|
||||
frame_header->size = fgetl(f);
|
||||
frame_header->magic = fgetw(f);
|
||||
@ -435,7 +460,7 @@ static void ase_file_read_frame_header(FILE *f, ASE_FrameHeader *frame_header)
|
||||
ase_file_read_padding(f, 6);
|
||||
}
|
||||
|
||||
static void ase_file_prepare_frame_header(FILE *f, ASE_FrameHeader *frame_header)
|
||||
static void ase_file_prepare_frame_header(FILE* f, ASE_FrameHeader* frame_header)
|
||||
{
|
||||
int pos = ftell(f);
|
||||
|
||||
@ -444,12 +469,10 @@ static void ase_file_prepare_frame_header(FILE *f, ASE_FrameHeader *frame_header
|
||||
frame_header->chunks = 0;
|
||||
frame_header->duration = 0;
|
||||
|
||||
current_frame_header = frame_header;
|
||||
|
||||
fseek(f, pos+16, SEEK_SET);
|
||||
}
|
||||
|
||||
static void ase_file_write_frame_header(FILE *f, ASE_FrameHeader *frame_header)
|
||||
static void ase_file_write_frame_header(FILE* f, ASE_FrameHeader* frame_header)
|
||||
{
|
||||
int pos = frame_header->size;
|
||||
int end = ftell(f);
|
||||
@ -465,24 +488,22 @@ static void ase_file_write_frame_header(FILE *f, ASE_FrameHeader *frame_header)
|
||||
ase_file_write_padding(f, 6);
|
||||
|
||||
fseek(f, end, SEEK_SET);
|
||||
|
||||
current_frame_header = NULL;
|
||||
}
|
||||
|
||||
static void ase_file_write_layers(FILE *f, Layer *layer)
|
||||
static void ase_file_write_layers(FILE* f, ASE_FrameHeader* frame_header, Layer* layer)
|
||||
{
|
||||
ase_file_write_layer_chunk(f, layer);
|
||||
ase_file_write_layer_chunk(f, frame_header, layer);
|
||||
|
||||
if (layer->isFolder()) {
|
||||
LayerIterator it = static_cast<LayerFolder*>(layer)->getLayerBegin();
|
||||
LayerIterator end = static_cast<LayerFolder*>(layer)->getLayerEnd();
|
||||
|
||||
for (; it != end; ++it)
|
||||
ase_file_write_layers(f, *it);
|
||||
ase_file_write_layers(f, frame_header, *it);
|
||||
}
|
||||
}
|
||||
|
||||
static void ase_file_write_cels(FILE *f, Sprite *sprite, Layer *layer, FrameNumber frame)
|
||||
static void ase_file_write_cels(FILE* f, ASE_FrameHeader* frame_header, Sprite* sprite, Layer* layer, FrameNumber frame)
|
||||
{
|
||||
if (layer->isImage()) {
|
||||
Cel* cel = static_cast<LayerImage*>(layer)->getCel(frame);
|
||||
@ -490,7 +511,7 @@ static void ase_file_write_cels(FILE *f, Sprite *sprite, Layer *layer, FrameNumb
|
||||
/* fop_error(fop, "New cel in frame %d, in layer %d\n", */
|
||||
/* frame, sprite_layer2index(sprite, layer)); */
|
||||
|
||||
ase_file_write_cel_chunk(f, cel, static_cast<LayerImage*>(layer), sprite);
|
||||
ase_file_write_cel_chunk(f, frame_header, cel, static_cast<LayerImage*>(layer), sprite);
|
||||
}
|
||||
}
|
||||
|
||||
@ -499,23 +520,23 @@ static void ase_file_write_cels(FILE *f, Sprite *sprite, Layer *layer, FrameNumb
|
||||
LayerIterator end = static_cast<LayerFolder*>(layer)->getLayerEnd();
|
||||
|
||||
for (; it != end; ++it)
|
||||
ase_file_write_cels(f, sprite, *it, frame);
|
||||
ase_file_write_cels(f, frame_header, sprite, *it, frame);
|
||||
}
|
||||
}
|
||||
|
||||
static void ase_file_read_padding(FILE *f, int bytes)
|
||||
static void ase_file_read_padding(FILE* f, int bytes)
|
||||
{
|
||||
for (int c=0; c<bytes; c++)
|
||||
fgetc(f);
|
||||
}
|
||||
|
||||
static void ase_file_write_padding(FILE *f, int bytes)
|
||||
static void ase_file_write_padding(FILE* f, int bytes)
|
||||
{
|
||||
for (int c=0; c<bytes; c++)
|
||||
fputc(0, f);
|
||||
}
|
||||
|
||||
static std::string ase_file_read_string(FILE *f)
|
||||
static std::string ase_file_read_string(FILE* f)
|
||||
{
|
||||
int length = fgetw(f);
|
||||
if (length == EOF)
|
||||
@ -530,7 +551,7 @@ static std::string ase_file_read_string(FILE *f)
|
||||
return string;
|
||||
}
|
||||
|
||||
static void ase_file_write_string(FILE *f, const std::string& string)
|
||||
static void ase_file_write_string(FILE* f, const std::string& string)
|
||||
{
|
||||
fputw(string.size(), f);
|
||||
|
||||
@ -538,28 +559,28 @@ static void ase_file_write_string(FILE *f, const std::string& string)
|
||||
fputc(string[c], f);
|
||||
}
|
||||
|
||||
static void ase_file_write_start_chunk(FILE *f, int type)
|
||||
static void ase_file_write_start_chunk(FILE* f, ASE_FrameHeader* frame_header, int type, ASE_Chunk* chunk)
|
||||
{
|
||||
current_frame_header->chunks++;
|
||||
frame_header->chunks++;
|
||||
|
||||
chunk_type = type;
|
||||
chunk_start = ftell(f);
|
||||
chunk->type = type;
|
||||
chunk->start = ftell(f);
|
||||
|
||||
fseek(f, chunk_start+6, SEEK_SET);
|
||||
fseek(f, chunk->start+6, SEEK_SET);
|
||||
}
|
||||
|
||||
static void ase_file_write_close_chunk(FILE *f)
|
||||
static void ase_file_write_close_chunk(FILE* f, ASE_Chunk* chunk)
|
||||
{
|
||||
int chunk_end = ftell(f);
|
||||
int chunk_size = chunk_end - chunk_start;
|
||||
int chunk_size = chunk_end - chunk->start;
|
||||
|
||||
fseek(f, chunk_start, SEEK_SET);
|
||||
fseek(f, chunk->start, SEEK_SET);
|
||||
fputl(chunk_size, f);
|
||||
fputw(chunk_type, f);
|
||||
fputw(chunk->type, f);
|
||||
fseek(f, chunk_end, SEEK_SET);
|
||||
}
|
||||
|
||||
static Palette *ase_file_read_color_chunk(FILE *f, Sprite *sprite, FrameNumber frame)
|
||||
static Palette* ase_file_read_color_chunk(FILE* f, Sprite* sprite, FrameNumber frame)
|
||||
{
|
||||
int i, c, r, g, b, packets, skip, size;
|
||||
Palette* pal = new Palette(*sprite->getPalette(frame));
|
||||
@ -587,7 +608,7 @@ static Palette *ase_file_read_color_chunk(FILE *f, Sprite *sprite, FrameNumber f
|
||||
return pal;
|
||||
}
|
||||
|
||||
static Palette *ase_file_read_color2_chunk(FILE *f, Sprite *sprite, FrameNumber frame)
|
||||
static Palette* ase_file_read_color2_chunk(FILE* f, Sprite* sprite, FrameNumber frame)
|
||||
{
|
||||
int i, c, r, g, b, packets, skip, size;
|
||||
Palette* pal = new Palette(*sprite->getPalette(frame));
|
||||
@ -614,12 +635,11 @@ static Palette *ase_file_read_color2_chunk(FILE *f, Sprite *sprite, FrameNumber
|
||||
}
|
||||
|
||||
/* writes the original color chunk in FLI files for the entire palette "pal" */
|
||||
static void ase_file_write_color2_chunk(FILE *f, Palette *pal)
|
||||
static void ase_file_write_color2_chunk(FILE* f, ASE_FrameHeader* frame_header, Palette* pal)
|
||||
{
|
||||
ChunkWriter chunk(f, frame_header, ASE_FILE_CHUNK_FLI_COLOR2);
|
||||
int c, color;
|
||||
|
||||
ase_file_write_start_chunk(f, ASE_FILE_CHUNK_FLI_COLOR2);
|
||||
|
||||
fputw(1, f); // number of packets
|
||||
|
||||
// First packet
|
||||
@ -632,14 +652,12 @@ static void ase_file_write_color2_chunk(FILE *f, Palette *pal)
|
||||
fputc(rgba_getg(color), f);
|
||||
fputc(rgba_getb(color), f);
|
||||
}
|
||||
|
||||
ase_file_write_close_chunk(f);
|
||||
}
|
||||
|
||||
static Layer *ase_file_read_layer_chunk(FILE *f, Sprite *sprite, Layer **previous_layer, int *current_level)
|
||||
static Layer* ase_file_read_layer_chunk(FILE* f, Sprite* sprite, Layer** previous_layer, int* current_level)
|
||||
{
|
||||
std::string name;
|
||||
Layer *layer = NULL;
|
||||
Layer* layer = NULL;
|
||||
/* read chunk data */
|
||||
int flags;
|
||||
int layer_type;
|
||||
@ -686,9 +704,9 @@ static Layer *ase_file_read_layer_chunk(FILE *f, Sprite *sprite, Layer **previou
|
||||
return layer;
|
||||
}
|
||||
|
||||
static void ase_file_write_layer_chunk(FILE *f, Layer *layer)
|
||||
static void ase_file_write_layer_chunk(FILE* f, ASE_FrameHeader* frame_header, Layer* layer)
|
||||
{
|
||||
ase_file_write_start_chunk(f, ASE_FILE_CHUNK_LAYER);
|
||||
ChunkWriter chunk(f, frame_header, ASE_FILE_CHUNK_LAYER);
|
||||
|
||||
// Flags
|
||||
fputw(layer->getFlags(), f);
|
||||
@ -716,8 +734,6 @@ static void ase_file_write_layer_chunk(FILE *f, Layer *layer)
|
||||
/* layer name */
|
||||
ase_file_write_string(f, layer->getName());
|
||||
|
||||
ase_file_write_close_chunk(f);
|
||||
|
||||
/* fop_error(fop, "Layer name \"%s\" child level: %d\n", layer->name, child_level); */
|
||||
}
|
||||
|
||||
@ -985,9 +1001,9 @@ static void write_compressed_image(FILE* f, Image* image)
|
||||
// Cel Chunk
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
static Cel *ase_file_read_cel_chunk(FILE *f, Sprite *sprite, FrameNumber frame,
|
||||
static Cel* ase_file_read_cel_chunk(FILE* f, Sprite* sprite, FrameNumber frame,
|
||||
PixelFormat pixelFormat,
|
||||
FileOp *fop, ASE_Header *header, size_t chunk_end)
|
||||
FileOp* fop, ASE_Header* header, size_t chunk_end)
|
||||
{
|
||||
/* read chunk data */
|
||||
LayerIndex layer_index = LayerIndex(fgetw(f));
|
||||
@ -1107,13 +1123,13 @@ static Cel *ase_file_read_cel_chunk(FILE *f, Sprite *sprite, FrameNumber frame,
|
||||
return newCel;
|
||||
}
|
||||
|
||||
static void ase_file_write_cel_chunk(FILE *f, Cel *cel, LayerImage *layer, Sprite *sprite)
|
||||
static void ase_file_write_cel_chunk(FILE* f, ASE_FrameHeader* frame_header, Cel* cel, LayerImage* layer, Sprite* sprite)
|
||||
{
|
||||
ChunkWriter chunk(f, frame_header, ASE_FILE_CHUNK_CEL);
|
||||
|
||||
int layer_index = sprite->layerToIndex(layer);
|
||||
int cel_type = ASE_FILE_COMPRESSED_CEL;
|
||||
|
||||
ase_file_write_start_chunk(f, ASE_FILE_CHUNK_CEL);
|
||||
|
||||
fputw(layer_index, f);
|
||||
fputw(cel->getX(), f);
|
||||
fputw(cel->getY(), f);
|
||||
@ -1193,14 +1209,12 @@ static void ase_file_write_cel_chunk(FILE *f, Cel *cel, LayerImage *layer, Sprit
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ase_file_write_close_chunk(f);
|
||||
}
|
||||
|
||||
static Mask *ase_file_read_mask_chunk(FILE *f)
|
||||
static Mask* ase_file_read_mask_chunk(FILE* f)
|
||||
{
|
||||
int c, u, v, byte;
|
||||
Mask *mask;
|
||||
Mask* mask;
|
||||
// Read chunk data
|
||||
int x = fgetw(f);
|
||||
int y = fgetw(f);
|
||||
@ -1225,13 +1239,13 @@ static Mask *ase_file_read_mask_chunk(FILE *f)
|
||||
return mask;
|
||||
}
|
||||
|
||||
static void ase_file_write_mask_chunk(FILE *f, Mask *mask)
|
||||
static void ase_file_write_mask_chunk(FILE* f, ASE_FrameHeader* frame_header, Mask* mask)
|
||||
{
|
||||
ChunkWriter chunk(f, frame_header, ASE_FILE_CHUNK_MASK);
|
||||
|
||||
int c, u, v, byte;
|
||||
const gfx::Rect& bounds(mask->getBounds());
|
||||
|
||||
ase_file_write_start_chunk(f, ASE_FILE_CHUNK_MASK);
|
||||
|
||||
fputw(bounds.x, f);
|
||||
fputw(bounds.y, f);
|
||||
fputw(bounds.w, f);
|
||||
@ -1250,8 +1264,6 @@ static void ase_file_write_mask_chunk(FILE *f, Mask *mask)
|
||||
byte |= (1<<(7-c));
|
||||
fputc(byte, f);
|
||||
}
|
||||
|
||||
ase_file_write_close_chunk(f);
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -147,7 +147,7 @@ FileOp* fop_to_load_document(const char* filename, int flags)
|
||||
return NULL;
|
||||
|
||||
// Get the extension of the filename (in lower case)
|
||||
base::string extension = base::string_to_lower(base::get_file_extension(filename));
|
||||
std::string extension = base::string_to_lower(base::get_file_extension(filename));
|
||||
|
||||
PRINTF("Loading file \"%s\" (%s)\n", filename, extension.c_str());
|
||||
|
||||
@ -244,7 +244,7 @@ FileOp* fop_to_save_document(Document* document)
|
||||
fop->document = document;
|
||||
|
||||
// Get the extension of the filename (in lower case)
|
||||
base::string extension = base::string_to_lower(base::get_file_extension(fop->document->getFilename()));
|
||||
std::string extension = base::string_to_lower(base::get_file_extension(fop->document->getFilename()));
|
||||
|
||||
PRINTF("Saving document \"%s\" (%s)\n",
|
||||
fop->document->getFilename().c_str(), extension.c_str());
|
||||
@ -258,7 +258,7 @@ FileOp* fop_to_save_document(Document* document)
|
||||
}
|
||||
|
||||
// Warnings
|
||||
base::string warnings;
|
||||
std::string warnings;
|
||||
fatal = false;
|
||||
|
||||
/* check image type support */
|
||||
|
@ -38,11 +38,21 @@ extern FileFormat* CreatePcxFormat();
|
||||
extern FileFormat* CreatePngFormat();
|
||||
extern FileFormat* CreateTgaFormat();
|
||||
|
||||
static FileFormatsManager* singleton = NULL;
|
||||
|
||||
// static
|
||||
FileFormatsManager& FileFormatsManager::instance()
|
||||
{
|
||||
static FileFormatsManager instance;
|
||||
return instance;
|
||||
if (!singleton)
|
||||
singleton = new FileFormatsManager();
|
||||
return *singleton;
|
||||
}
|
||||
|
||||
// static
|
||||
void FileFormatsManager::destroyInstance()
|
||||
{
|
||||
delete singleton;
|
||||
singleton = NULL;
|
||||
}
|
||||
|
||||
FileFormatsManager::~FileFormatsManager()
|
||||
|
@ -36,6 +36,7 @@ namespace app {
|
||||
public:
|
||||
// Returns a singleton of this class.
|
||||
static FileFormatsManager& instance();
|
||||
static void destroyInstance();
|
||||
|
||||
virtual ~FileFormatsManager();
|
||||
|
||||
|
@ -103,11 +103,36 @@ FileFormat* CreateGifFormat()
|
||||
static int interlaced_offset[] = { 0, 4, 2, 1 };
|
||||
static int interlaced_jumps[] = { 8, 8, 4, 2 };
|
||||
|
||||
struct GifFilePtr {
|
||||
public:
|
||||
typedef int (*CloseFunc)(GifFileType*, int*);
|
||||
|
||||
GifFilePtr(GifFileType* ptr, CloseFunc closeFunc) :
|
||||
m_ptr(ptr), m_closeFunc(closeFunc) {
|
||||
}
|
||||
|
||||
~GifFilePtr() {
|
||||
int errCode;
|
||||
m_closeFunc(m_ptr, &errCode);
|
||||
}
|
||||
|
||||
operator GifFileType*() {
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
GifFileType* operator->() {
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
GifFileType* m_ptr;
|
||||
CloseFunc m_closeFunc;
|
||||
};
|
||||
|
||||
bool GifFormat::onLoad(FileOp* fop)
|
||||
{
|
||||
UniquePtr<GifFileType, int(*)(GifFileType*)> gif_file
|
||||
(DGifOpenFileHandle(open_file_descriptor_with_exception(fop->filename, "rb")),
|
||||
DGifCloseFile);
|
||||
int errCode;
|
||||
GifFilePtr gif_file(DGifOpenFileHandle(open_file_descriptor_with_exception(fop->filename, "rb"), &errCode), &DGifCloseFile);
|
||||
|
||||
if (!gif_file) {
|
||||
fop_error(fop, "Error loading GIF header.\n");
|
||||
@ -131,9 +156,10 @@ bool GifFormat::onLoad(FileOp* fop)
|
||||
// Setup the first palette using the global color map.
|
||||
ColorMapObject* colormap = gif_file->SColorMap;
|
||||
for (int i=0; i<colormap->ColorCount; ++i) {
|
||||
current_palette->setEntry(i, rgba(colormap->Colors[i].Red,
|
||||
colormap->Colors[i].Green,
|
||||
colormap->Colors[i].Blue, 255));
|
||||
current_palette->setEntry(i,
|
||||
rgba(colormap->Colors[i].Red,
|
||||
colormap->Colors[i].Green,
|
||||
colormap->Colors[i].Blue, 255));
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -214,7 +240,7 @@ bool GifFormat::onLoad(FileOp* fop)
|
||||
for (int y = 0; y < frame_h; ++y) {
|
||||
addr = frame_image->getPixelAddress(0, y);
|
||||
if (DGifGetLine(gif_file, addr, frame_w) == GIF_ERROR)
|
||||
throw Exception("Invalid image data (%d).\n", GifLastError());
|
||||
throw Exception("Invalid image data (%d).\n", gif_file->Error);
|
||||
}
|
||||
}
|
||||
|
||||
@ -492,9 +518,8 @@ void GifFormat::onDestroyData(FileOp* fop)
|
||||
#ifdef ENABLE_SAVE
|
||||
bool GifFormat::onSave(FileOp* fop)
|
||||
{
|
||||
UniquePtr<GifFileType, int(*)(GifFileType*)> gif_file
|
||||
(EGifOpenFileHandle(open_file_descriptor_with_exception(fop->filename, "wb")),
|
||||
EGifCloseFile);
|
||||
int errCode;
|
||||
GifFilePtr gif_file(EGifOpenFileHandle(open_file_descriptor_with_exception(fop->filename, "wb"), &errCode), &EGifCloseFile);
|
||||
|
||||
if (!gif_file)
|
||||
throw Exception("Error creating GIF file.\n");
|
||||
@ -510,7 +535,7 @@ bool GifFormat::onSave(FileOp* fop)
|
||||
|
||||
Palette* current_palette = sprite->getPalette(FrameNumber(0));
|
||||
Palette* previous_palette = current_palette;
|
||||
ColorMapObject* color_map = MakeMapObject(current_palette->size(), NULL);
|
||||
ColorMapObject* color_map = GifMakeMapObject(current_palette->size(), NULL);
|
||||
for (int i = 0; i < current_palette->size(); ++i) {
|
||||
color_map->Colors[i].Red = rgba_getr(current_palette->getEntry(i));
|
||||
color_map->Colors[i].Green = rgba_getg(current_palette->getEntry(i));
|
||||
@ -603,20 +628,36 @@ bool GifFormat::onSave(FileOp* fop)
|
||||
|
||||
// Specify loop extension.
|
||||
if (frame_num == 0 && loop >= 0) {
|
||||
unsigned char extension_bytes[11];
|
||||
if (EGifPutExtensionLeader(gif_file, APPLICATION_EXT_FUNC_CODE) == GIF_ERROR)
|
||||
throw Exception("Error writing GIF graphics extension record (header section).");
|
||||
|
||||
unsigned char extension_bytes[11];
|
||||
memcpy(extension_bytes, "NETSCAPE2.0", 11);
|
||||
if (EGifPutExtensionFirst(gif_file, APPLICATION_EXT_FUNC_CODE, 11, extension_bytes) == GIF_ERROR)
|
||||
throw Exception("Error writing GIF graphics extension record for frame %d.\n", (int)frame_num);
|
||||
if (EGifPutExtensionBlock(gif_file, 11, extension_bytes) == GIF_ERROR)
|
||||
throw Exception("Error writing GIF graphics extension record (first block).");
|
||||
|
||||
extension_bytes[0] = 1;
|
||||
extension_bytes[1] = (loop & 0xff);
|
||||
extension_bytes[2] = (loop >> 8) & 0xff;
|
||||
if (EGifPutExtensionNext(gif_file, APPLICATION_EXT_FUNC_CODE, 3, extension_bytes) == GIF_ERROR)
|
||||
throw Exception("Error writing GIF graphics extension record for frame %d.\n", (int)frame_num);
|
||||
if (EGifPutExtensionBlock(gif_file, 3, extension_bytes) == GIF_ERROR)
|
||||
throw Exception("Error writing GIF graphics extension record (second block).");
|
||||
|
||||
if (EGifPutExtensionLast(gif_file, APPLICATION_EXT_FUNC_CODE, 0, NULL) == GIF_ERROR)
|
||||
throw Exception("Error writing GIF graphics extension record for frame %d.\n", (int)frame_num);
|
||||
if (EGifPutExtensionTrailer(gif_file) == GIF_ERROR)
|
||||
throw Exception("Error writing GIF graphics extension record (trailer section).");
|
||||
}
|
||||
|
||||
// Add Aseprite block (at this moment, it's empty).
|
||||
if (frame_num == 0) {
|
||||
if (EGifPutExtensionLeader(gif_file, APPLICATION_EXT_FUNC_CODE) == GIF_ERROR)
|
||||
throw Exception("Error writing GIF comment (header section).");
|
||||
|
||||
unsigned char extension_bytes[11];
|
||||
memcpy(extension_bytes, "ASEPRITE1.0", 11);
|
||||
if (EGifPutExtensionBlock(gif_file, sizeof(extension_bytes), extension_bytes) == GIF_ERROR)
|
||||
throw Exception("Error writing GIF comment (first block).");
|
||||
|
||||
if (EGifPutExtensionTrailer(gif_file) == GIF_ERROR)
|
||||
throw Exception("Error writing GIF comment (trailer section).");
|
||||
}
|
||||
|
||||
// Write graphics extension record (to save the duration of the
|
||||
@ -640,7 +681,7 @@ bool GifFormat::onSave(FileOp* fop)
|
||||
// Image color map
|
||||
ColorMapObject* image_color_map = NULL;
|
||||
if (current_palette != previous_palette) {
|
||||
image_color_map = MakeMapObject(current_palette->size(), NULL);
|
||||
image_color_map = GifMakeMapObject(current_palette->size(), NULL);
|
||||
for (int i = 0; i < current_palette->size(); ++i) {
|
||||
image_color_map->Colors[i].Red = rgba_getr(current_palette->getEntry(i));
|
||||
image_color_map->Colors[i].Green = rgba_getg(current_palette->getEntry(i));
|
||||
|
@ -24,9 +24,9 @@
|
||||
|
||||
namespace app {
|
||||
|
||||
base::string show_file_selector(const base::string& title,
|
||||
const base::string& initialPath,
|
||||
const base::string& showExtensions)
|
||||
std::string show_file_selector(const std::string& title,
|
||||
const std::string& initialPath,
|
||||
const std::string& showExtensions)
|
||||
{
|
||||
FileSelector fileSelector;
|
||||
return fileSelector.show(title, initialPath, showExtensions);
|
||||
|
@ -20,13 +20,13 @@
|
||||
#define APP_FILE_SELECTOR_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "base/string.h"
|
||||
#include <string>
|
||||
|
||||
namespace app {
|
||||
|
||||
base::string show_file_selector(const base::string& title,
|
||||
const base::string& initialPath,
|
||||
const base::string& showExtensions);
|
||||
std::string show_file_selector(const std::string& title,
|
||||
const std::string& initialPath,
|
||||
const std::string& showExtensions);
|
||||
|
||||
} // namespace app
|
||||
|
||||
|
@ -105,9 +105,9 @@ namespace app {
|
||||
// a position in the file-system
|
||||
class FileItem : public IFileItem {
|
||||
public:
|
||||
base::string keyname;
|
||||
base::string filename;
|
||||
base::string displayname;
|
||||
std::string keyname;
|
||||
std::string filename;
|
||||
std::string displayname;
|
||||
FileItem* parent;
|
||||
FileItemList children;
|
||||
unsigned int version;
|
||||
@ -138,22 +138,22 @@ public:
|
||||
bool isFolder() const;
|
||||
bool isBrowsable() const;
|
||||
|
||||
base::string getKeyName() const;
|
||||
base::string getFileName() const;
|
||||
base::string getDisplayName() const;
|
||||
std::string getKeyName() const;
|
||||
std::string getFileName() const;
|
||||
std::string getDisplayName() const;
|
||||
|
||||
IFileItem* getParent() const;
|
||||
const FileItemList& getChildren();
|
||||
|
||||
bool hasExtension(const base::string& csv_extensions);
|
||||
bool hasExtension(const std::string& csv_extensions);
|
||||
|
||||
BITMAP* getThumbnail();
|
||||
void setThumbnail(BITMAP* thumbnail);
|
||||
|
||||
};
|
||||
|
||||
typedef std::map<base::string, FileItem*> FileItemMap;
|
||||
typedef std::map<base::string, BITMAP*> ThumbnailMap;
|
||||
typedef std::map<std::string, FileItem*> FileItemMap;
|
||||
typedef std::map<std::string, BITMAP*> ThumbnailMap;
|
||||
|
||||
// the root of the file-system
|
||||
static FileItem* rootitem = NULL;
|
||||
@ -180,15 +180,15 @@ static unsigned int current_file_system_version = 0;
|
||||
static LPITEMIDLIST clone_pidl(LPITEMIDLIST pidl);
|
||||
static LPITEMIDLIST remove_last_pidl(LPITEMIDLIST pidl);
|
||||
static void free_pidl(LPITEMIDLIST pidl);
|
||||
static base::string get_key_for_pidl(LPITEMIDLIST pidl);
|
||||
static std::string get_key_for_pidl(LPITEMIDLIST pidl);
|
||||
|
||||
static FileItem* get_fileitem_by_fullpidl(LPITEMIDLIST pidl, bool create_if_not);
|
||||
static void put_fileitem(FileItem* fileitem);
|
||||
#else
|
||||
static FileItem* get_fileitem_by_path(const base::string& path, bool create_if_not);
|
||||
static FileItem* get_fileitem_by_path(const std::string& path, bool create_if_not);
|
||||
static void for_each_child_callback(const char *filename, int attrib, int param);
|
||||
static base::string remove_backslash_if_needed(const base::string& filename);
|
||||
static base::string get_key_for_filename(const base::string& filename);
|
||||
static std::string remove_backslash_if_needed(const std::string& filename);
|
||||
static std::string get_key_for_filename(const std::string& filename);
|
||||
static void put_fileitem(FileItem* fileitem);
|
||||
#endif
|
||||
|
||||
@ -204,10 +204,14 @@ FileSystemModule::FileSystemModule()
|
||||
|
||||
#ifdef USE_PIDLS
|
||||
/* get the IMalloc interface */
|
||||
SHGetMalloc(&shl_imalloc);
|
||||
HRESULT hr = SHGetMalloc(&shl_imalloc);
|
||||
if (hr != S_OK)
|
||||
throw std::runtime_error("Error initializing file system. Report this problem. (SHGetMalloc failed.)");
|
||||
|
||||
/* get desktop IShellFolder interface */
|
||||
SHGetDesktopFolder(&shl_idesktop);
|
||||
hr = SHGetDesktopFolder(&shl_idesktop);
|
||||
if (hr != S_OK)
|
||||
throw std::runtime_error("Error initializing file system. Report this problem. (SHGetDesktopFolder failed.)");
|
||||
#endif
|
||||
|
||||
// first version of the file system
|
||||
@ -313,7 +317,7 @@ IFileItem* FileSystemModule::getRootFileItem()
|
||||
return fileitem;
|
||||
}
|
||||
|
||||
IFileItem* FileSystemModule::getFileItemFromPath(const base::string& path)
|
||||
IFileItem* FileSystemModule::getFileItemFromPath(const std::string& path)
|
||||
{
|
||||
IFileItem* fileitem = NULL;
|
||||
|
||||
@ -321,7 +325,7 @@ IFileItem* FileSystemModule::getFileItemFromPath(const base::string& path)
|
||||
|
||||
#ifdef USE_PIDLS
|
||||
{
|
||||
ULONG cbEaten;
|
||||
ULONG cbEaten = 0UL;
|
||||
LPITEMIDLIST fullpidl = NULL;
|
||||
SFGAOF attrib = SFGAO_FOLDER;
|
||||
|
||||
@ -344,7 +348,7 @@ IFileItem* FileSystemModule::getFileItemFromPath(const base::string& path)
|
||||
}
|
||||
#else
|
||||
{
|
||||
base::string buf = remove_backslash_if_needed(path);
|
||||
std::string buf = remove_backslash_if_needed(path);
|
||||
fileitem = get_fileitem_by_path(buf, true);
|
||||
}
|
||||
#endif
|
||||
@ -354,11 +358,11 @@ IFileItem* FileSystemModule::getFileItemFromPath(const base::string& path)
|
||||
return fileitem;
|
||||
}
|
||||
|
||||
bool FileSystemModule::dirExists(const base::string& path)
|
||||
bool FileSystemModule::dirExists(const std::string& path)
|
||||
{
|
||||
struct al_ffblk info;
|
||||
int ret;
|
||||
base::string path2 = base::join_path(path, "*.*");
|
||||
std::string path2 = base::join_path(path, "*.*");
|
||||
|
||||
ret = al_findfirst(path2.c_str(), &info, FA_ALL);
|
||||
al_findclose(&info);
|
||||
@ -389,21 +393,21 @@ bool FileItem::isBrowsable() const
|
||||
#endif
|
||||
}
|
||||
|
||||
base::string FileItem::getKeyName() const
|
||||
std::string FileItem::getKeyName() const
|
||||
{
|
||||
ASSERT(this->keyname != NOTINITIALIZED);
|
||||
|
||||
return this->keyname;
|
||||
}
|
||||
|
||||
base::string FileItem::getFileName() const
|
||||
std::string FileItem::getFileName() const
|
||||
{
|
||||
ASSERT(this->filename != NOTINITIALIZED);
|
||||
|
||||
return this->filename;
|
||||
}
|
||||
|
||||
base::string FileItem::getDisplayName() const
|
||||
std::string FileItem::getDisplayName() const
|
||||
{
|
||||
ASSERT(this->displayname != NOTINITIALIZED);
|
||||
|
||||
@ -443,24 +447,27 @@ const FileItemList& FileItem::getChildren()
|
||||
#ifdef USE_PIDLS
|
||||
{
|
||||
IShellFolder* pFolder = NULL;
|
||||
HRESULT hr;
|
||||
|
||||
if (this == rootitem)
|
||||
pFolder = shl_idesktop;
|
||||
else
|
||||
shl_idesktop->BindToObject(this->fullpidl,
|
||||
NULL,
|
||||
IID_IShellFolder,
|
||||
(LPVOID *)&pFolder);
|
||||
else {
|
||||
hr = shl_idesktop->BindToObject(this->fullpidl,
|
||||
NULL, IID_IShellFolder, (LPVOID *)&pFolder);
|
||||
|
||||
if (hr != S_OK)
|
||||
pFolder = NULL;
|
||||
}
|
||||
|
||||
if (pFolder != NULL) {
|
||||
IEnumIDList *pEnum = NULL;
|
||||
ULONG c, fetched;
|
||||
|
||||
/* get the interface to enumerate subitems */
|
||||
pFolder->EnumObjects(win_get_window(),
|
||||
SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &pEnum);
|
||||
hr = pFolder->EnumObjects(win_get_window(),
|
||||
SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &pEnum);
|
||||
|
||||
if (pEnum != NULL) {
|
||||
if (hr == S_OK && pEnum != NULL) {
|
||||
LPITEMIDLIST itempidl[256];
|
||||
SFGAOF attribs[256];
|
||||
|
||||
@ -534,7 +541,9 @@ const FileItemList& FileItem::getChildren()
|
||||
for (it=this->children.begin();
|
||||
it!=this->children.end(); ) {
|
||||
child = static_cast<FileItem*>(*it);
|
||||
if (child->removed) {
|
||||
ASSERT(child != NULL);
|
||||
|
||||
if (child && child->removed) {
|
||||
it = this->children.erase(it);
|
||||
|
||||
fileitems_map->erase(fileitems_map->find(child->keyname));
|
||||
@ -551,7 +560,7 @@ const FileItemList& FileItem::getChildren()
|
||||
return this->children;
|
||||
}
|
||||
|
||||
bool FileItem::hasExtension(const base::string& csv_extensions)
|
||||
bool FileItem::hasExtension(const std::string& csv_extensions)
|
||||
{
|
||||
ASSERT(this->filename != NOTINITIALIZED);
|
||||
|
||||
@ -709,15 +718,16 @@ static void update_by_pidl(FileItem* fileitem)
|
||||
STRRET strret;
|
||||
WCHAR pszName[MAX_PATH];
|
||||
IShellFolder *pFolder = NULL;
|
||||
HRESULT hr;
|
||||
|
||||
if (fileitem == rootitem)
|
||||
pFolder = shl_idesktop;
|
||||
else {
|
||||
ASSERT(fileitem->parent);
|
||||
shl_idesktop->BindToObject(fileitem->parent->fullpidl,
|
||||
NULL,
|
||||
IID_IShellFolder,
|
||||
(LPVOID *)&pFolder);
|
||||
hr = shl_idesktop->BindToObject(fileitem->parent->fullpidl,
|
||||
NULL, IID_IShellFolder, (LPVOID *)&pFolder);
|
||||
if (hr != S_OK)
|
||||
pFolder = NULL;
|
||||
}
|
||||
|
||||
/****************************************/
|
||||
@ -863,7 +873,7 @@ static void free_pidl(LPITEMIDLIST pidl)
|
||||
shl_imalloc->Free(pidl);
|
||||
}
|
||||
|
||||
static base::string get_key_for_pidl(LPITEMIDLIST pidl)
|
||||
static std::string get_key_for_pidl(LPITEMIDLIST pidl)
|
||||
{
|
||||
#if 0
|
||||
char *key = base_malloc(get_pidl_size(pidl)+1);
|
||||
@ -894,7 +904,8 @@ static base::string get_key_for_pidl(LPITEMIDLIST pidl)
|
||||
if (shl_idesktop->GetDisplayNameOf(pidl,
|
||||
SHGDN_INFOLDER | SHGDN_FORPARSING,
|
||||
&strret) == S_OK) {
|
||||
StrRetToBuf(&strret, pidl, pszName, MAX_PATH);
|
||||
if (StrRetToBuf(&strret, pidl, pszName, MAX_PATH) != S_OK)
|
||||
pszName[0] = 0;
|
||||
|
||||
//PRINTF("FS: + %s\n", pszName);
|
||||
|
||||
@ -984,7 +995,7 @@ static void put_fileitem(FileItem* fileitem)
|
||||
// Allegro for_each_file: Portable
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
static FileItem* get_fileitem_by_path(const base::string& path, bool create_if_not)
|
||||
static FileItem* get_fileitem_by_path(const std::string& path, bool create_if_not)
|
||||
{
|
||||
if (path.empty())
|
||||
return rootitem;
|
||||
@ -1013,7 +1024,7 @@ static FileItem* get_fileitem_by_path(const base::string& path, bool create_if_n
|
||||
|
||||
// get the parent
|
||||
{
|
||||
base::string parent_path = remove_backslash_if_needed(base::join_path(base::get_file_path(path), ""));
|
||||
std::string parent_path = remove_backslash_if_needed(base::join_path(base::get_file_path(path), ""));
|
||||
fileitem->parent = get_fileitem_by_path(parent_path, true);
|
||||
}
|
||||
|
||||
@ -1055,7 +1066,7 @@ static void for_each_child_callback(const char *filename, int attrib, int param)
|
||||
fileitem->insertChildSorted(child);
|
||||
}
|
||||
|
||||
static base::string remove_backslash_if_needed(const base::string& filename)
|
||||
static std::string remove_backslash_if_needed(const std::string& filename)
|
||||
{
|
||||
if (!filename.empty() && base::is_path_separator(*(filename.end()-1))) {
|
||||
int len = filename.size();
|
||||
@ -1074,9 +1085,9 @@ static base::string remove_backslash_if_needed(const base::string& filename)
|
||||
return filename;
|
||||
}
|
||||
|
||||
static base::string get_key_for_filename(const base::string& filename)
|
||||
static std::string get_key_for_filename(const std::string& filename)
|
||||
{
|
||||
base::string buf(filename);
|
||||
std::string buf(filename);
|
||||
|
||||
#if !defined CASE_SENSITIVE
|
||||
buf.tolower();
|
||||
|
@ -20,8 +20,9 @@
|
||||
#define APP_FILE_SYSTEM_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "base/string.h"
|
||||
#include "base/mutex.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct BITMAP;
|
||||
@ -49,10 +50,27 @@ namespace app {
|
||||
|
||||
// Returns the FileItem through the specified "path".
|
||||
// Warning: You have to call path.fix_separators() before.
|
||||
IFileItem* getFileItemFromPath(const base::string& path);
|
||||
IFileItem* getFileItemFromPath(const std::string& path);
|
||||
|
||||
bool dirExists(const base::string& path);
|
||||
bool dirExists(const std::string& path);
|
||||
|
||||
void lock() { m_mutex.lock(); }
|
||||
void unlock() { m_mutex.unlock(); }
|
||||
|
||||
private:
|
||||
base::mutex m_mutex;
|
||||
};
|
||||
|
||||
class LockFS {
|
||||
public:
|
||||
LockFS(FileSystemModule* fs) : m_fs(fs) {
|
||||
m_fs->lock();
|
||||
}
|
||||
~LockFS() {
|
||||
m_fs->unlock();
|
||||
}
|
||||
private:
|
||||
FileSystemModule* m_fs;
|
||||
};
|
||||
|
||||
class IFileItem {
|
||||
@ -62,14 +80,14 @@ namespace app {
|
||||
virtual bool isFolder() const = 0;
|
||||
virtual bool isBrowsable() const = 0;
|
||||
|
||||
virtual base::string getKeyName() const = 0;
|
||||
virtual base::string getFileName() const = 0;
|
||||
virtual base::string getDisplayName() const = 0;
|
||||
virtual std::string getKeyName() const = 0;
|
||||
virtual std::string getFileName() const = 0;
|
||||
virtual std::string getDisplayName() const = 0;
|
||||
|
||||
virtual IFileItem* getParent() const = 0;
|
||||
virtual const FileItemList& getChildren() = 0;
|
||||
|
||||
virtual bool hasExtension(const base::string& csv_extensions) = 0;
|
||||
virtual bool hasExtension(const std::string& csv_extensions) = 0;
|
||||
|
||||
virtual BITMAP* getThumbnail() = 0;
|
||||
virtual void setThumbnail(BITMAP* thumbnail) = 0;
|
||||
|
@ -34,6 +34,32 @@ namespace app {
|
||||
return child;
|
||||
}
|
||||
|
||||
class finder {
|
||||
public:
|
||||
finder(ui::Widget* parent) : m_parent(parent) {
|
||||
}
|
||||
|
||||
finder& operator>>(const char* id) {
|
||||
m_lastId = id;
|
||||
return *this;
|
||||
}
|
||||
|
||||
finder& operator>>(const std::string& id) {
|
||||
m_lastId = id;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
finder& operator>>(T*& child) {
|
||||
child = app::find_widget<T>(m_parent, m_lastId.c_str());
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
ui::Widget* m_parent;
|
||||
std::string m_lastId;
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
||||
#endif
|
||||
|
@ -52,7 +52,7 @@ GuiXml::GuiXml()
|
||||
m_doc = app::open_xml(rf.filename());
|
||||
}
|
||||
|
||||
base::string GuiXml::version()
|
||||
std::string GuiXml::version()
|
||||
{
|
||||
TiXmlHandle handle(m_doc);
|
||||
TiXmlElement* xmlKey = handle.FirstChild("gui").ToElement();
|
||||
|
@ -21,7 +21,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "app/xml_document.h"
|
||||
#include "base/string.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace app {
|
||||
|
||||
@ -43,7 +44,7 @@ namespace app {
|
||||
return m_doc->Value();
|
||||
}
|
||||
|
||||
base::string version();
|
||||
std::string version();
|
||||
|
||||
private:
|
||||
GuiXml();
|
||||
|
84
src/app/handle_anidir.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2014 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/handle_anidir.h"
|
||||
|
||||
#include "app/settings/document_settings.h"
|
||||
#include "raster/sprite.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
raster::FrameNumber calculate_next_frame(
|
||||
raster::Sprite* sprite,
|
||||
raster::FrameNumber frame,
|
||||
IDocumentSettings* docSettings,
|
||||
bool& pingPongForward)
|
||||
{
|
||||
FrameNumber first = FrameNumber(0);
|
||||
FrameNumber last = sprite->getLastFrame();
|
||||
|
||||
if (docSettings->getLoopAnimation()) {
|
||||
FrameNumber loopBegin, loopEnd;
|
||||
docSettings->getLoopRange(&loopBegin, &loopEnd);
|
||||
if (loopBegin < first) loopBegin = first;
|
||||
if (loopEnd > last) loopEnd = last;
|
||||
|
||||
first = loopBegin;
|
||||
last = loopEnd;
|
||||
}
|
||||
|
||||
switch (docSettings->getAnimationDirection()) {
|
||||
|
||||
case IDocumentSettings::AniDir_Normal:
|
||||
frame = frame.next();
|
||||
if (frame > last) frame = first;
|
||||
break;
|
||||
|
||||
case IDocumentSettings::AniDir_Reverse:
|
||||
frame = frame.previous();
|
||||
if (frame < first) frame = last;
|
||||
break;
|
||||
|
||||
case IDocumentSettings::AniDir_PingPong:
|
||||
if (pingPongForward) {
|
||||
frame = frame.next();
|
||||
if (frame > last) {
|
||||
frame = last.previous();
|
||||
if (frame < first) frame = first;
|
||||
pingPongForward = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
frame = frame.previous();
|
||||
if (frame < first) {
|
||||
frame = first.next();
|
||||
if (frame > last) frame = last;
|
||||
pingPongForward = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
} // namespace app
|