Revision e4237c21
Added by Leszek Koltunski almost 8 years ago
src/main/java/org/distorted/examples/save/SaveRenderer.java | ||
---|---|---|
22 | 22 |
import java.io.File; |
23 | 23 |
import java.io.IOException; |
24 | 24 |
import java.io.InputStream; |
25 |
import java.util.Vector; |
|
25 |
import java.nio.ByteBuffer; |
|
26 |
import java.nio.ByteOrder; |
|
26 | 27 |
|
27 | 28 |
import javax.microedition.khronos.egl.EGLConfig; |
28 | 29 |
import javax.microedition.khronos.opengles.GL10; |
... | ... | |
31 | 32 |
|
32 | 33 |
import org.distorted.library.Distorted; |
33 | 34 |
import org.distorted.library.DistortedBitmap; |
34 |
import org.distorted.library.message.EffectListener; |
|
35 |
import org.distorted.library.message.EffectMessage; |
|
36 | 35 |
import org.distorted.library.EffectTypes; |
37 | 36 |
import org.distorted.library.type.Float1D; |
38 | 37 |
import org.distorted.library.type.Float2D; |
... | ... | |
45 | 44 |
import android.opengl.GLES20; |
46 | 45 |
import android.opengl.GLSurfaceView; |
47 | 46 |
import android.os.Environment; |
48 |
import android.widget.Toast; |
|
49 | 47 |
|
50 | 48 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
51 | 49 |
|
52 |
class SaveRenderer implements GLSurfaceView.Renderer ,EffectListener
|
|
50 |
class SaveRenderer implements GLSurfaceView.Renderer |
|
53 | 51 |
{ |
54 | 52 |
private GLSurfaceView mView; |
55 | 53 |
private static DistortedBitmap mGirl; |
... | ... | |
61 | 59 |
private int bmpHeight, bmpWidth; |
62 | 60 |
private static int scrHeight, scrWidth; |
63 | 61 |
private static float boobsSink; |
62 |
private static boolean isSaving = false; |
|
63 |
private static String mPath; |
|
64 | 64 |
|
65 |
private static class SaveInfo |
|
66 |
{ |
|
67 |
private long id; |
|
68 |
private String path; |
|
69 |
|
|
70 |
SaveInfo(long id, String path) |
|
71 |
{ |
|
72 |
this.id = id; |
|
73 |
this.path = path; |
|
74 |
} |
|
75 |
} |
|
76 |
|
|
77 |
private static Vector<SaveInfo> mSaveInfo; // Vector keeping all the information about the PATH |
|
78 |
// where current 'SAVE' effects are saving to and also |
|
79 |
// the IDs of the effects. |
|
80 |
// We need to have a whole Vector because there can be |
|
81 |
// many concurrent 'SAVE' operations (click 'SAVE', |
|
82 |
// don't wait for the Toast to appear, immediately |
|
83 |
// click again! ) |
|
65 |
private static SaveWorkerThread mWorkerThread =null; |
|
84 | 66 |
|
85 | 67 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
86 | 68 |
|
... | ... | |
101 | 83 |
diSink.setCount(0.5f); |
102 | 84 |
diSink.setDuration(0); |
103 | 85 |
diSink.add(s0); |
104 |
|
|
105 |
mSaveInfo = new Vector<>(); |
|
106 | 86 |
} |
107 | 87 |
|
108 | 88 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
109 | 89 |
|
110 |
public static void setSize(float s)
|
|
90 |
public static void startThread(Activity act)
|
|
111 | 91 |
{ |
112 |
boobsSink = s; |
|
113 |
s0.set(boobsSink); |
|
92 |
if( mWorkerThread ==null ) mWorkerThread = new SaveWorkerThread(); |
|
93 |
|
|
94 |
mWorkerThread.startSending(act); |
|
114 | 95 |
} |
115 | 96 |
|
116 | 97 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
117 | 98 |
|
118 |
public static void Save()
|
|
99 |
public static void stopThread()
|
|
119 | 100 |
{ |
120 |
File file;
|
|
121 |
int lowestNotFound = 1;
|
|
122 |
String path;
|
|
101 |
mWorkerThread.stopSending();
|
|
102 |
mWorkerThread = null;
|
|
103 |
}
|
|
123 | 104 |
|
124 |
while(true) |
|
125 |
{ |
|
126 |
path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/girl" + lowestNotFound +".png"; |
|
127 |
file = new File(path); |
|
105 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
128 | 106 |
|
129 |
if( !file.exists() ) |
|
130 |
{ |
|
131 |
long id= mGirl.savePNG(file.getAbsolutePath(),0,0,scrWidth,scrHeight); |
|
132 |
mSaveInfo.add(new SaveInfo(id,path)); |
|
133 |
break; |
|
134 |
} |
|
135 |
lowestNotFound++; |
|
136 |
} |
|
107 |
public static void setSize(float s) |
|
108 |
{ |
|
109 |
boobsSink = s; |
|
110 |
s0.set(boobsSink); |
|
137 | 111 |
} |
138 | 112 |
|
139 | 113 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
140 |
// the library sending messages to us. This does not run on this UI thread! |
|
141 | 114 |
|
142 |
public void effectMessage(final EffectMessage em, final long effectID, final int effectName, final long bitmapID, final String message)
|
|
115 |
public static void Save()
|
|
143 | 116 |
{ |
144 |
int numSaves = mSaveInfo.size(); |
|
145 |
int found = -1; |
|
146 |
|
|
147 |
for(int i=0; i<numSaves; i++) // doesn't need to be synchronized with Save() |
|
148 |
{ // because over there we only add() and here we only |
|
149 |
if( effectID == mSaveInfo.get(i).id ) // remove() - and even if we add() in between of |
|
150 |
{ // computing the 'numSaves' above and this loop, |
|
151 |
found = i; // it still doesn't matter :) |
|
152 |
break; |
|
153 |
} |
|
154 |
} |
|
155 |
|
|
156 |
if( found>=0 ) // the message really is about one of the 'SAVE' effects in execution now |
|
117 |
if( isSaving==false ) |
|
157 | 118 |
{ |
158 |
Activity act = (Activity)mView.getContext(); |
|
159 |
final String path = mSaveInfo.get(found).path; |
|
160 |
mSaveInfo.remove(found); |
|
119 |
isSaving = true; |
|
161 | 120 |
|
162 |
switch(em) |
|
121 |
File file; |
|
122 |
int lowestNotFound = 1; |
|
123 |
|
|
124 |
while(true) |
|
163 | 125 |
{ |
164 |
case EFFECT_FINISHED: act.runOnUiThread(new Runnable() |
|
165 |
{ |
|
166 |
public void run() |
|
167 |
{ |
|
168 |
Toast.makeText(mView.getContext(), |
|
169 |
"Saving to \n\n"+path+"\n\nsuccessful" , |
|
170 |
Toast.LENGTH_LONG).show(); |
|
171 |
} |
|
172 |
}); |
|
173 |
break; |
|
174 |
|
|
175 |
case EFFECT_FAILED : act.runOnUiThread(new Runnable() |
|
176 |
{ |
|
177 |
public void run() |
|
178 |
{ |
|
179 |
Toast.makeText(mView.getContext(), |
|
180 |
"Saving to \n\n"+path+"\n\n failed: "+"\n\n"+message , |
|
181 |
Toast.LENGTH_LONG).show(); |
|
182 |
} |
|
183 |
}); |
|
184 |
break; |
|
185 |
|
|
186 |
default : break; |
|
126 |
mPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/girl" + lowestNotFound +".png"; |
|
127 |
file = new File(mPath); |
|
128 |
|
|
129 |
if( !file.exists() ) break; |
|
130 |
|
|
131 |
lowestNotFound++; |
|
187 | 132 |
} |
188 | 133 |
} |
189 | 134 |
} |
... | ... | |
196 | 141 |
GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT); |
197 | 142 |
|
198 | 143 |
mGirl.draw(System.currentTimeMillis()); |
144 |
|
|
145 |
if( isSaving ) // we should save the buffer to location pointed at by mPath |
|
146 |
{ |
|
147 |
ByteBuffer buf = ByteBuffer.allocateDirect( scrWidth*scrHeight*4 ); |
|
148 |
buf.order(ByteOrder.LITTLE_ENDIAN); |
|
149 |
GLES20.glReadPixels( 0, 0, scrWidth, scrHeight , GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buf); |
|
150 |
|
|
151 |
mWorkerThread.newBuffer(buf,scrWidth,scrHeight,mPath); |
|
152 |
|
|
153 |
isSaving = false; |
|
154 |
} |
|
199 | 155 |
} |
200 | 156 |
|
201 | 157 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
247 | 203 |
bmpWidth = bitmap.getWidth(); |
248 | 204 |
|
249 | 205 |
mGirl = new DistortedBitmap(bitmap, 30); |
250 |
mGirl.addEventListener(this); |
|
251 | 206 |
|
252 | 207 |
mGirl.sink( diSink, sinkRegion, pLeft ); |
253 | 208 |
mGirl.sink( diSink, sinkRegion, pRight); |
Also available in: Unified diff
Move the 'Save' effect to the Application and remove the 'OTHER' effect queue