diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..5bdb3d8 --- /dev/null +++ b/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000..d1ffe54 --- /dev/null +++ b/.project @@ -0,0 +1,33 @@ + + + SLWP + + + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + diff --git a/AndroidManifest.xml b/AndroidManifest.xml new file mode 100644 index 0000000..fb8df99 --- /dev/null +++ b/AndroidManifest.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/console_bkg.bmp b/assets/console_bkg.bmp new file mode 100644 index 0000000..d32ee4c Binary files /dev/null and b/assets/console_bkg.bmp differ diff --git a/assets/file.bmp b/assets/file.bmp new file mode 100644 index 0000000..f074f7b Binary files /dev/null and b/assets/file.bmp differ diff --git a/assets/final_cloud.png b/assets/final_cloud.png new file mode 100644 index 0000000..d718d54 Binary files /dev/null and b/assets/final_cloud.png differ diff --git a/assets/gui_transparent.fragment b/assets/gui_transparent.fragment new file mode 100644 index 0000000..bd2926c --- /dev/null +++ b/assets/gui_transparent.fragment @@ -0,0 +1,10 @@ +precision lowp float; + +uniform sampler2D Texture; +varying vec2 texCoord; + +void main() +{ + vec4 texColor = texture2D(Texture,texCoord).rgba; + gl_FragColor = vec4(texColor.rgb, texColor.a); +} diff --git a/assets/gui_transparent.vertex b/assets/gui_transparent.vertex new file mode 100644 index 0000000..ad425c2 --- /dev/null +++ b/assets/gui_transparent.vertex @@ -0,0 +1,11 @@ +attribute vec3 vPosition; +attribute vec2 vTexCoord; +varying vec2 texCoord; +uniform mat4 ProjectionMatrix; + +void main() +{ + //480x320 + gl_Position = ProjectionMatrix * vec4(vPosition.xyz, 1.0); + texCoord = vTexCoord; +} \ No newline at end of file diff --git a/assets/gui_transparent_clip.fragment b/assets/gui_transparent_clip.fragment new file mode 100644 index 0000000..b2154f8 --- /dev/null +++ b/assets/gui_transparent_clip.fragment @@ -0,0 +1,13 @@ +precision lowp float; + +uniform sampler2D Texture; +varying vec2 texCoord; +varying vec3 vertexPos; + +void main() +{ + vec4 texColor = texture2D(Texture,texCoord).rgba; + + gl_FragColor = vec4(texColor.rgb, texColor.a); //day + +} diff --git a/assets/gui_transparent_clip.vertex b/assets/gui_transparent_clip.vertex new file mode 100644 index 0000000..8150ba9 --- /dev/null +++ b/assets/gui_transparent_clip.vertex @@ -0,0 +1,13 @@ +attribute vec3 vPosition; +attribute vec2 vTexCoord; +varying vec2 texCoord; +varying vec3 vertexPos; +uniform mat4 ProjectionMatrix; + +void main() +{ + //480x320 + gl_Position = ProjectionMatrix * vec4(vPosition.xyz, 1.0); + vertexPos = vPosition.xyz; + texCoord = vTexCoord; +} \ No newline at end of file diff --git a/assets/ice1.lm1 b/assets/ice1.lm1 new file mode 100644 index 0000000..09df5c4 Binary files /dev/null and b/assets/ice1.lm1 differ diff --git a/assets/ice1.png b/assets/ice1.png new file mode 100644 index 0000000..ca8ff0a Binary files /dev/null and b/assets/ice1.png differ diff --git a/assets/ice2.lm1 b/assets/ice2.lm1 new file mode 100644 index 0000000..0dd19c6 Binary files /dev/null and b/assets/ice2.lm1 differ diff --git a/assets/ice2.png b/assets/ice2.png new file mode 100644 index 0000000..7b7d417 Binary files /dev/null and b/assets/ice2.png differ diff --git a/assets/ice3.lm1 b/assets/ice3.lm1 new file mode 100644 index 0000000..052459f Binary files /dev/null and b/assets/ice3.lm1 differ diff --git a/assets/ice3.png b/assets/ice3.png new file mode 100644 index 0000000..6fd99b2 Binary files /dev/null and b/assets/ice3.png differ diff --git a/assets/ice4.lm1 b/assets/ice4.lm1 new file mode 100644 index 0000000..1372e99 Binary files /dev/null and b/assets/ice4.lm1 differ diff --git a/assets/ice5.lm1 b/assets/ice5.lm1 new file mode 100644 index 0000000..dfd1e7c Binary files /dev/null and b/assets/ice5.lm1 differ diff --git a/assets/ice6.lm1 b/assets/ice6.lm1 new file mode 100644 index 0000000..561f0fb Binary files /dev/null and b/assets/ice6.lm1 differ diff --git a/assets/ices.xml b/assets/ices.xml new file mode 100644 index 0000000..5136844 --- /dev/null +++ b/assets/ices.xml @@ -0,0 +1,29 @@ + + +ice1.lm10.013.01102.0 +ice2.lm1-3.014.070 +ice3.lm1-4.015.01602.0 +ice6.lm17.013.5240 +ice4.lm14.015.01.4 +ice5.lm1-6.014.060 +ice6.lm1-1.014.0 +ice1.lm15.013.01.3 +ice3.lm1-5.015.030 + + +ice6.lm19.012.0 +ice4.lm111.011.01302.1 + + +ice4.lm113.010.02401.5 + +ice1.lm114.06.0 +ice2.lm116.04.51.8 +ice3.lm118.02.0340 + +ice4.lm117.02.02.0 +ice2.lm118.0-1.5601.5 +ice1.lm115.0-5.51302.0 +ice5.lm112.0-8.0160 + + \ No newline at end of file diff --git a/assets/mountain.lm1 b/assets/mountain.lm1 new file mode 100644 index 0000000..b47222d Binary files /dev/null and b/assets/mountain.lm1 differ diff --git a/assets/mountain.png b/assets/mountain.png new file mode 100644 index 0000000..6cf7a3b Binary files /dev/null and b/assets/mountain.png differ diff --git a/assets/sky.png b/assets/sky.png new file mode 100644 index 0000000..62ae31f Binary files /dev/null and b/assets/sky.png differ diff --git a/assets/sky_night.png b/assets/sky_night.png new file mode 100644 index 0000000..25790d7 Binary files /dev/null and b/assets/sky_night.png differ diff --git a/assets/snow.png b/assets/snow.png new file mode 100644 index 0000000..84e4550 Binary files /dev/null and b/assets/snow.png differ diff --git a/assets/test_norm.fragment b/assets/test_norm.fragment new file mode 100644 index 0000000..309f7b0 --- /dev/null +++ b/assets/test_norm.fragment @@ -0,0 +1,56 @@ +precision lowp float; + +uniform sampler2D Texture; +uniform sampler2D NormalMap; +uniform vec3 CamPos; +uniform float WaterScale; +varying vec2 texCoord; +uniform float Time; + +void main() +{ + + vec2 localTexCoord = texCoord; + + vec3 camVec = CamPos.xyz; + float len = length(camVec); + float squeeze = 0.5*(len / CamPos.y ); + + squeeze = min(squeeze, 4.0); + + //if (squeeze>15.0) squeeze = 15.0; + + vec3 v3 = vec3(0.0,1.0,0.0); + vec3 v2 = vec3(1.0,0.0,0.0); + vec3 v1 = vec3(0.0,0.0,1.0); + + mat3 rot; + + rot[0] = v1; + rot[1] = v2; + rot[2] = v3; + + float sinx = 0.025*sin(Time+localTexCoord.x*2.0); + + vec3 NVec1 = texture2D(NormalMap, vec2(-Time*0.04 + localTexCoord.x*WaterScale + sinx, -Time*0.04 + squeeze*localTexCoord.y*WaterScale - sinx)).rgb; + vec3 NVec2 = texture2D(NormalMap, vec2( Time*0.04 + squeeze*localTexCoord.y*WaterScale - sinx, -Time*0.04 + (1.0-localTexCoord.x)*WaterScale + sinx)).rgb; + + NVec1 = (NVec1 -0.5) * 2.0; + NVec2 = (NVec2 -0.5) * 2.0; + + + vec3 NVec = 0.5*NVec1 + 0.5*NVec2; + NVec = rot * NVec; + + float d = 1.0/(len+0.05); + + d = min(d, 2.0); + + localTexCoord.x = max(min(localTexCoord.x + d * NVec.x, 1.0), 0.0); + localTexCoord.y = max(min(localTexCoord.y - d * NVec.z, 1.0), 0.0); + + vec4 specular = vec4(0.8, 0.8, 0.8, 1.0)* (1.0-pow(max(dot(vec3(0.0,1.0,0.0), normalize(NVec)),0.0),2.0)); + + + gl_FragColor = texture2D(Texture, localTexCoord).rgba + specular + vec4(0.0, 0.05, 0.1, 0.0); +} diff --git a/assets/test_norm.vertex b/assets/test_norm.vertex new file mode 100644 index 0000000..3c8592f --- /dev/null +++ b/assets/test_norm.vertex @@ -0,0 +1,12 @@ +attribute vec3 vPosition; +attribute vec3 Normal; +attribute vec2 vTexCoord; +varying vec2 texCoord; +uniform mat4 ProjectionMatrix; + +void main() +{ + //480x320 + gl_Position = ProjectionMatrix * vec4(vPosition.xyz, 1.0); + texCoord = vTexCoord; +} \ No newline at end of file diff --git a/assets/test_parallax.fragment b/assets/test_parallax.fragment new file mode 100644 index 0000000..5b38c57 --- /dev/null +++ b/assets/test_parallax.fragment @@ -0,0 +1,34 @@ +precision lowp float; + +uniform sampler2D Texture; +uniform sampler2D NormalMap; +uniform vec3 LightDirection; +varying vec2 texCoord; + +varying vec3 camVec; +varying vec3 normVec; + +void main() +{ + + vec3 cVec = normalize(camVec); + + float parallax = 0.035; + + //double refinement + float height = texture2D(NormalMap, texCoord.xy).a; + float offset = parallax * (2.0 * height - 1.0); + vec2 parallaxTexCoord = texCoord.xy + offset * cVec.xy; + height += texture2D(NormalMap, parallaxTexCoord).a; + + offset = parallax * (height - 1.0); + + parallaxTexCoord = texCoord.xy + offset * cVec.xy; + + vec3 nvec = normalize(normVec); + + + float cosf = max(0.0, dot(nvec, -LightDirection)); + + gl_FragColor = vec4((texture2D(Texture, parallaxTexCoord).rgb * (cosf * 0.75 + 0.25)), 1.0); +} diff --git a/assets/test_parallax.vertex b/assets/test_parallax.vertex new file mode 100644 index 0000000..88bc4e2 --- /dev/null +++ b/assets/test_parallax.vertex @@ -0,0 +1,30 @@ +attribute vec3 vPosition; +attribute vec3 Normal; +attribute vec3 Tangent; +attribute vec3 Binormal; +attribute vec2 vTexCoord; + +uniform mat4 ProjectionMatrix; +uniform vec3 CamPos; + +varying vec2 texCoord; +varying vec3 camVec; +varying vec3 normVec; + +void main() +{ + //480x320 + gl_Position = ProjectionMatrix * vec4(vPosition.xyz, 1.0); + texCoord = vTexCoord; + + vec3 cVec = (CamPos - vPosition.xyz); + + mat3 rot; + rot[0] = Tangent; + rot[1] = Binormal; + rot[2] = Normal; + + camVec = cVec * rot; + + normVec = Normal; +} \ No newline at end of file diff --git a/assets/test_simplelight.fragment b/assets/test_simplelight.fragment new file mode 100644 index 0000000..510db92 --- /dev/null +++ b/assets/test_simplelight.fragment @@ -0,0 +1,26 @@ +precision lowp float; + +uniform sampler2D Texture; +uniform sampler2D NormalMap; +uniform vec3 LightDirection; +uniform float TimeOfDayCoef1; +uniform float TimeOfDayCoef2; +uniform vec3 TimeOfDayColor; +varying vec2 texCoord; + +varying vec3 camVec; +varying vec3 normVec; + +void main() +{ + + vec3 nvec = normalize(normVec); + + float cosf = max(0.0, dot(nvec, -LightDirection)); + + //gl_FragColor = vec4((texture2D(Texture, texCoord).rgb * (cosf * 0.75 + 0.25)), 1.0); //day + //gl_FragColor = vec4((texture2D(Texture, texCoord).rgb * (cosf * 0.5 + 0.25)), 1.0); //twilight + //gl_FragColor = vec4(((texture2D(Texture, texCoord).rgb + vec3(0.0, 0.1, 0.2)) * (0.4)), 1.0); + + gl_FragColor = vec4(((texture2D(Texture, texCoord).rgb + TimeOfDayColor) * (cosf * TimeOfDayCoef1 + TimeOfDayCoef2)), 1.0); +} diff --git a/assets/test_simplelight.vertex b/assets/test_simplelight.vertex new file mode 100644 index 0000000..88bc4e2 --- /dev/null +++ b/assets/test_simplelight.vertex @@ -0,0 +1,30 @@ +attribute vec3 vPosition; +attribute vec3 Normal; +attribute vec3 Tangent; +attribute vec3 Binormal; +attribute vec2 vTexCoord; + +uniform mat4 ProjectionMatrix; +uniform vec3 CamPos; + +varying vec2 texCoord; +varying vec3 camVec; +varying vec3 normVec; + +void main() +{ + //480x320 + gl_Position = ProjectionMatrix * vec4(vPosition.xyz, 1.0); + texCoord = vTexCoord; + + vec3 cVec = (CamPos - vPosition.xyz); + + mat3 rot; + rot[0] = Tangent; + rot[1] = Binormal; + rot[2] = Normal; + + camVec = cVec * rot; + + normVec = Normal; +} \ No newline at end of file diff --git a/assets/water_nmap.png b/assets/water_nmap.png new file mode 100644 index 0000000..98dcb2f Binary files /dev/null and b/assets/water_nmap.png differ diff --git a/jni/Android.mk b/jni/Android.mk new file mode 100644 index 0000000..caf8206 --- /dev/null +++ b/jni/Android.mk @@ -0,0 +1,77 @@ +# Copyright (C) 2009 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + + +LPATH := $(call my-dir) + +ENGINE_PATH = $(SalmonEnginePathCygwin) + +BOOST_PATH = $(LibsPathCygwin)/boost_1_52_0 + +OGG_PATH = $(LibsPathCygwin)/libogg-1.3.0 + +VORBIS_PATH = $(LibsPathCygwin)/libvorbis-1.3.2 + +SQUIRREL_PATH = $(LibsPathCygwin)/sqplus + +LIBPNG_PATH = $(LibsPathCygwin)/libpng_1.4.1_android + +ZIP_PATH = $(LibsPathCygwin)/julienr-libzip-android/jni + +#====== ENGINE AND LIBS ===================== + +include $(ENGINE_PATH)/Android_Salmon_Engine.mk + +#================= THE GAME ======================= + + +LOCAL_PATH:= $(LPATH) + +include $(CLEAR_VARS) + +LOCAL_CFLAGS := -DTARGET_ANDROID -DNOSOUND -std=gnu++11 --std=c++11 +LOCAL_STATIC_LIBRARIES := boost +LOCAL_STATIC_LIBRARIES += squirrel +LOCAL_STATIC_LIBRARIES += png_lib +LOCAL_STATIC_LIBRARIES += zip +LOCAL_SHARED_LIBRARIES := SalmonEngine +LOCAL_SHARED_LIBRARIES += gnustl_shared +LOCAL_C_INCLUDES := $(ENGINE_PATH) +LOCAL_C_INCLUDES += $(BOOST_PATH) +LOCAL_C_INCLUDES += $(VORBIS_PATH)/include +LOCAL_C_INCLUDES += $(VORBIS_PATH)/include/vorbis +LOCAL_C_INCLUDES += $(VORBIS_PATH)/lib +LOCAL_C_INCLUDES += $(VORBIS_PATH)/lib/books +LOCAL_C_INCLUDES += $(VORBIS_PATH)/lib/modes +LOCAL_C_INCLUDES += $(OGG_PATH)/include +LOCAL_C_INCLUDES += $(OGG_PATH)/include/ogg +LOCAL_C_INCLUDES += $(SQUIRREL_PATH)/include +LOCAL_C_INCLUDES += $(SQUIRREL_PATH)/sqplus +LOCAL_C_INCLUDES += $(SQUIRREL_PATH)/squirrel +LOCAL_C_INCLUDES += $(SQUIRREL_PATH)/sqstdlib +LOCAL_C_INCLUDES += $(LIBPNG_PATH) +LOCAL_C_INCLUDES += $(ZIP_PATH) +LOCAL_MODULE := SalmonWallpaper +LOCAL_SRC_FILES := main_code.cpp +LOCAL_SRC_FILES += android_api.cpp + +LOCAL_LDLIBS := -lGLESv2 +LOCAL_LDLIBS += -llog -Wl + +#debug +#LOCAL_CFLAGS += -g -ggdb -O0 +#LOCAL_LDLIBS += -g -ggdb + +include $(BUILD_SHARED_LIBRARY) diff --git a/jni/Application.mk b/jni/Application.mk new file mode 100644 index 0000000..b096c4c --- /dev/null +++ b/jni/Application.mk @@ -0,0 +1,3 @@ +APP_STL := gnustl_shared +APP_CPPFLAGS += -fexceptions +APP_CPPFLAGS += -frtti \ No newline at end of file diff --git a/jni/android_api.cpp b/jni/android_api.cpp new file mode 100644 index 0000000..e154036 --- /dev/null +++ b/jni/android_api.cpp @@ -0,0 +1,49 @@ +#include "android_api.h" + +#include "main_code.h" +#include "boost\thread.hpp" + +TAndroidApplication* Application = NULL; + + +float lastOffsetX = 0.5f; + +const float CONST_ANGLE_SHIFT = 45.f; + +int TimeOfDayPref = 0; +bool SnowPref = false; + +bool OffsetChanged = false; + +JNIEXPORT void JNICALL Java_fishrungames_mountainwallpaper_JniWrapper_SetTimeOfDayPref(JNIEnv * env, jobject obj, jint timeofday) +{ + TimeOfDayPref = timeofday; +} +JNIEXPORT void JNICALL Java_fishrungames_mountainwallpaper_JniWrapper_SetSnowPref(JNIEnv * env, jobject obj, jboolean snow) +{ + SnowPref = snow; +} + +JNIEXPORT void JNICALL Java_fishrungames_mountainwallpaper_JniWrapper_Init(JNIEnv * env, jobject obj, jint width, jint height) +{ + + Application = JniInitApp(width, height, 800.f, 480.f); + + boost::get(Renderer->Camera).SetAlpha((lastOffsetX) * pi / 180.f); + Application->SkyTexShift = lastOffsetX*0.01f; + + +} + + +JNIEXPORT void JNICALL Java_fishrungames_mountainwallpaper_JniWrapper_SetOffset(JNIEnv * env, jobject obj, jfloat offsetX, jfloat offsetY) +{ + + if (Renderer != NULL) + { + OffsetChanged = true; + Application->SkyTexShift = offsetX*0.01f; + lastOffsetX = offsetX; + boost::get(Renderer->Camera).SetAlpha((lastOffsetX) * pi / 180.f); + } +} diff --git a/jni/android_api.h b/jni/android_api.h new file mode 100644 index 0000000..117ed80 --- /dev/null +++ b/jni/android_api.h @@ -0,0 +1,30 @@ +#ifndef ANDROID_API_H_INCLUDED +#define ANDROID_API_H_INCLUDED + +#include +#include + +#include +#include +#include + +#include "boost/shared_ptr.hpp" + +#include "main_code.h" + +using namespace SE; + +extern "C" { + + JNIEXPORT void JNICALL Java_fishrungames_mountainwallpaper_JniWrapper_SetTimeOfDayPref(JNIEnv * env, jobject obj, jint timeofday); + + JNIEXPORT void JNICALL Java_fishrungames_mountainwallpaper_JniWrapper_SetSnowPref(JNIEnv * env, jobject obj, jboolean snow); + + JNIEXPORT void JNICALL Java_fishrungames_mountainwallpaper_JniWrapper_Init(JNIEnv * env, jobject obj, jint width, jint height); + + JNIEXPORT void JNICALL Java_fishrungames_mountainwallpaper_JniWrapper_SetOffset(JNIEnv * env, jobject obj, jfloat offsetX, jfloat offsetY); + + }; + + +#endif diff --git a/jni/main_code.cpp b/jni/main_code.cpp new file mode 100644 index 0000000..eda5405 --- /dev/null +++ b/jni/main_code.cpp @@ -0,0 +1,550 @@ +#include "main_code.h" +#ifdef TARGET_ANDROID +#include "android_api.h" +#endif +#include +#include +#include +#include + +#include "include/Engine.h" + +#include "main_code.h" + +bool makeShot = true; + + +extern int TimeOfDayPref; +extern bool SnowPref; + +extern float lastOffsetX; + +#ifdef TARGET_WIN32 +int TimeOfDayPref = 0; +bool SnowPref = false; + +#else +extern int TimeOfDayPref; +extern bool SnowPref; + +#endif + + +boost::mutex m2; + + +class LoadingQueueVisitor : public boost::static_visitor +{ +public: + void operator()(boost::function f) const + { + f(); + } + + void operator()(boost::function f) const + { + f(); + } + + void operator()(boost::function f) const + { + f(); + } +}; + +TAndroidApplication::TAndroidApplication() + : TApplication() + , Inited(false) + , Loaded(false) + , LiteModel(NULL) + , WaterTimer(0) + , SnowTimer(0) + , CloudTimer(0) + , SkyTexShift(0) + , WaveDir(false) +{ +} + + +void TAndroidApplication::Serialize(boost::property_tree::ptree& propertyTree) +{ + BOOST_FOREACH(boost::property_tree::ptree::value_type &v, propertyTree.get_child("Ices")) + { + + std::string modelName = v.second.get("ModelName"); + float posx = v.second.get("PosX"); + float posz = v.second.get("PosZ"); + + float angle = v.second.get("Angle", 0.f); + float scale = v.second.get("Scale", 1.f); + + mat3 m(vec4(0, cos(angle*pi/360.f), 0, sin(angle*pi/360.f))); + + IceModel.push_back(TLiteModel()); + IceModel[IceModel.size()-1].LoadModel(modelName); + IceModel[IceModel.size()-1].RotateModel(m); + IceModel[IceModel.size()-1].ScaleModel(scale); + IceModel[IceModel.size()-1].MoveModel(vec3(posx, 0, posz)); + + + IceModel[IceModel.size()-1].UpdateVBO(); + + + + } +} + + + +void TAndroidApplication::LoadModels() +{ + mat3 m(vec4(0,1*sin(pi/8 + pi/2),0,1*cos(pi/8 + pi/2))); + + LiteModel = new TLiteModel; + LiteModel->LoadModel("mountain.lm1"); + LiteModel->ScaleModel(0.5f); + LiteModel->RotateModel(m); + LiteModel->MoveModel(vec3(0, 0, 0)); + LiteModel->UpdateVBO(); + + std::shared_ptr p = FileToPropertyTree("ices.xml"); + + Serialize(*p); + +} + +void TAndroidApplication::AddFrameBuffers() +{ + ResourceManager->FrameManager.AddFrameRenderBuffer("WaterFrame", 256, 256); + ResourceManager->FrameManager.AddFrameRenderBuffer("ScreenshotFrame", 512, 512); + +} + +void TAndroidApplication::DrawSceneWithoutWater(bool inv) +{ + + + Renderer->PushProjectionMatrix(1,1); + Renderer->LoadIdentity(); + + if (inv) + { + + + if (TimeOfDayPref == 2) + { + glBindTexture(GL_TEXTURE_2D, ResourceManager->TexList["sky_night.png"]); + } + else + { + glBindTexture(GL_TEXTURE_2D, ResourceManager->TexList["sky.png"]); + } + Renderer->DrawRect(vec2(0.0f, 0.56f), vec2(1.f, 0.f), vec2(0.5f + SkyTexShift, 0.f), vec2(1.f + SkyTexShift, 1.f)); + + if (TimeOfDayPref == 1) + { + glClear(GL_DEPTH_BUFFER_BIT); + glBindTexture(GL_TEXTURE_2D, ResourceManager->TexList["final_cloud.png"]); + Renderer->DrawRect(vec2(0.0f, 0.56f), vec2(4.f, 0.f), vec2(0.0f + SkyTexShift + CloudTimer, 0.f), vec2(1.f + SkyTexShift + CloudTimer, 0.5f)); + } + } + else + { + if (TimeOfDayPref == 2) + { + glBindTexture(GL_TEXTURE_2D, ResourceManager->TexList["sky_night.png"]); + } + else + { + glBindTexture(GL_TEXTURE_2D, ResourceManager->TexList["sky.png"]); + } + Renderer->DrawRect(vec2(0.0f, 0.54f), vec2(1.f, 1.f), vec2(0.5f + SkyTexShift, 0.f), vec2(1.f + SkyTexShift, 1.f)); + + if (TimeOfDayPref == 1) + { + glClear(GL_DEPTH_BUFFER_BIT); + glBindTexture(GL_TEXTURE_2D, ResourceManager->TexList["final_cloud.png"]); + Renderer->DrawRect(vec2(0.0f, 0.54f), vec2(4.f, 1.f), vec2(0.0f + SkyTexShift + CloudTimer, 0.f), vec2(1.f + SkyTexShift + CloudTimer, 0.5f)); + } + } + + + + Renderer->PopProjectionMatrix(); + + glClear(GL_DEPTH_BUFFER_BIT); + Renderer->SetGLCamView(); + + if (inv) + { + Renderer->TranslateMatrix(vec3(0,0.1f,0)); + Renderer->ScaleMatrix(vec3(1, -1, 1)); + } + + Renderer->PushShader("SimplelightShader"); + + vec3 dayColor = vec3(0,0,0); + vec3 nightColor = vec3(0, 0.1f, 0.2f); + + if (TimeOfDayPref == 0) + { + RenderUniform3fv("TimeOfDayColor", dayColor.v); + RenderUniform1f("TimeOfDayCoef1", 0.75f); + RenderUniform1f("TimeOfDayCoef2", 0.25f); + } + else + if (TimeOfDayPref == 1) + { + RenderUniform3fv("TimeOfDayColor", dayColor.v); + RenderUniform1f("TimeOfDayCoef1", 0.5f); + RenderUniform1f("TimeOfDayCoef2", 0.25f); + } + else + { + RenderUniform3fv("TimeOfDayColor", nightColor.v); + RenderUniform1f("TimeOfDayCoef1", 0.0f); + RenderUniform1f("TimeOfDayCoef2", 0.4f); + } + + + Renderer->PushPerspectiveProjectionMatrix(pi/6, Renderer->GetMatrixWidth() / Renderer->GetMatrixHeight(), 1.f, 450.f); + + LiteModel->DrawVBO(); + + for (int i=0; iPopProjectionMatrix(); + + Renderer->PopShader(); +} + +void TAndroidApplication::DrawSnow() +{ + + Renderer->PushProjectionMatrix(1,1); + + Renderer->LoadIdentity(); + + const float multiply_x = 4; + const float multiply_y = 2; + + Renderer->DrawRect(vec2(0, 0), vec2(1.f, 1.f), vec2(-SkyTexShift, SnowTimer), vec2(multiply_x - SkyTexShift, multiply_y + SnowTimer)); + glClear(GL_DEPTH_BUFFER_BIT); + Renderer->DrawRect(vec2(0, 0), vec2(1.f, 1.f), vec2(SnowTimer*0.7f+0.3f - SkyTexShift, SnowTimer+0.7f), vec2(multiply_x - SkyTexShift + SnowTimer*0.7f+0.3f, multiply_y + SnowTimer+0.7f)); + glClear(GL_DEPTH_BUFFER_BIT); + Renderer->DrawRect(vec2(0, 0), vec2(1.f, 1.f), vec2(SnowTimer*0.4f+0.7f - SkyTexShift, SnowTimer+0.3f), vec2(multiply_x - SkyTexShift + SnowTimer*0.4f+0.7f, multiply_y + SnowTimer+0.3f)); + + Renderer->PopProjectionMatrix(); +} + +void TAndroidApplication::DrawAllScene(bool toScreen) +{ + glClearColor(0.f, 0.f, 0.f, 1.0f); + //glClearColor(1.f, 1.f, 1.f, 1.0f); + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + + Renderer->PushMatrix(); + Renderer->SetGLCamView(); + + Renderer->PushShader("ClipShader"); + + + Renderer->SwitchToFrameBuffer("WaterFrame"); + Renderer->SetGLCamView(); + Renderer->ScaleMatrix(vec3(1, -1, 1)); + + + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + + DrawSceneWithoutWater(true); + + Renderer->ScaleMatrix(vec3(1, -1, 1)); + + if (toScreen) + { + Renderer->SwitchToScreen(); + } + else + { + Renderer->SwitchToFrameBuffer("ScreenshotFrame"); + } + + Renderer->SetGLCamView(); + + Renderer->PushShader("NormShader"); + RenderUniform1f("Time", WaterTimer); + if (Renderer->GetScreenWidth() < 600) + { + RenderUniform1f("WaterScale", 0.7f); + } + else + { + RenderUniform1f("WaterScale", 1.f); + } + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, ResourceManager->TexList["water_nmap.png"]); + glActiveTexture(GL_TEXTURE0); + if (toScreen) + { + Renderer->SetFullScreenViewport(); + } + else + { + Renderer->SetFrameViewport("ScreenshotFrame"); + } + Renderer->DrawFramePartScreen("WaterFrame", vec2(0, 0), vec2(1.f, 0.54f)); + Renderer->PopShader(); + + glClear(GL_DEPTH_BUFFER_BIT); + + Renderer->SetGLCamView(); + + + DrawSceneWithoutWater(false); + + glClear(GL_DEPTH_BUFFER_BIT); + + glBindTexture(GL_TEXTURE_2D, ResourceManager->TexList["snow.png"]); + + if (SnowPref) + { + DrawSnow(); + } + + Renderer->PopShader(); + + Renderer->PopMatrix(); +} + +void TAndroidApplication::InnerInit() +{ + m2.lock(); + + CheckGlError(); + + glEnable(GL_BLEND); + + *Console<<"Inner init go!\n"; + +#ifdef TARGET_ANDROID + ResourceManager->PathToResources = ""; +#endif +#ifdef TARGET_WIN32 + ResourceManager->PathToResources = "../../assets/"; +#endif + ResourceManager->ShaderManager.AddShader("DefaultShader", "gui_transparent.vertex", "gui_transparent.fragment"); + Renderer->PushShader("DefaultShader"); + + LoadingQueue.push_back(boost::function(boost::bind(&TShaderManager::AddShader, &(ResourceManager->ShaderManager), "ClipShader", "gui_transparent_clip.vertex", "gui_transparent_clip.fragment"))); + LoadingQueue.push_back(boost::function(boost::bind(&TShaderManager::AddShader, &(ResourceManager->ShaderManager), "NormShader", "test_norm.vertex", "test_norm.fragment"))); + LoadingQueue.push_back(boost::function(boost::bind(&TShaderManager::AddShader, &(ResourceManager->ShaderManager), "ParallaxShader", "test_parallax.vertex", "test_parallax.fragment"))); + LoadingQueue.push_back(boost::function(boost::bind(&TShaderManager::AddShader, &(ResourceManager->ShaderManager), "SimplelightShader", "test_simplelight.vertex", "test_simplelight.fragment"))); + + if (IsFileExistsInUserData("file.bmp")) + { + ResourceManager->TexList.AddTextureFromUserdata("file.bmp", "ScreenshotTexture"); + } + else + { + ResourceManager->TexList.AddTexture("file.bmp", "ScreenshotTexture"); + } + + LoadingQueue.push_back(boost::function(boost::bind(&TTextureListClass::AddTexture, &(ResourceManager->TexList), "console_bkg.bmp", ""))); + LoadingQueue.push_back(boost::function(boost::bind(&TTextureListClass::AddTexture, &(ResourceManager->TexList), "water_nmap.png", ""))); + LoadingQueue.push_back(boost::function(boost::bind(&TTextureListClass::AddTexture, &(ResourceManager->TexList), "sky.png", ""))); + LoadingQueue.push_back(boost::function(boost::bind(&TTextureListClass::AddTexture, &(ResourceManager->TexList), "sky_night.png", ""))); + LoadingQueue.push_back(boost::function(boost::bind(&TTextureListClass::AddTexture, &(ResourceManager->TexList), "snow.png", ""))); + LoadingQueue.push_back(boost::function(boost::bind(&TTextureListClass::AddTexture, &(ResourceManager->TexList), "final_cloud.png", ""))); + + + LoadingQueue.push_back(boost::function(boost::bind(&TModelManager::AddLiteModel, &(ResourceManager->ModelManager), "mountain.lm1", ""))); + LoadingQueue.push_back(boost::function(boost::bind(&TModelManager::AddLiteModel, &(ResourceManager->ModelManager), "ice1.lm1", ""))); + LoadingQueue.push_back(boost::function(boost::bind(&TModelManager::AddLiteModel, &(ResourceManager->ModelManager), "ice2.lm1", ""))); + LoadingQueue.push_back(boost::function(boost::bind(&TModelManager::AddLiteModel, &(ResourceManager->ModelManager), "ice3.lm1", ""))); + LoadingQueue.push_back(boost::function(boost::bind(&TModelManager::AddLiteModel, &(ResourceManager->ModelManager), "ice4.lm1", ""))); + LoadingQueue.push_back(boost::function(boost::bind(&TModelManager::AddLiteModel, &(ResourceManager->ModelManager), "ice5.lm1", ""))); + LoadingQueue.push_back(boost::function(boost::bind(&TModelManager::AddLiteModel, &(ResourceManager->ModelManager), "ice6.lm1", ""))); + + LoadingQueue.push_back(boost::function(boost::bind(&TAndroidApplication::LoadModels, this))); + LoadingQueue.push_back(boost::function(boost::bind(&TAndroidApplication::AddFrameBuffers, this))); + + + + //LoadModels(); + + CheckGlError(); + + + boost::get(Renderer->Camera).MovePhi(pi/32); + + + if (Renderer->GetScreenWidth() > Renderer->GetScreenHeight()) + { + boost::get(Renderer->Camera).MoveDist(30.f); + } + + else + { + boost::get(Renderer->Camera).MoveDist(45.f); + } + + boost::get(Renderer->Camera).CalcCamVec(); + + CheckGlError(); + + ResourceManager->LightManager.SetLightOn(); + + ResourceManager->LightManager.SetLightDirection(vec3(1, -1, 0)); + + //AddFrameBuffers(); + + //Renderer->SetPerspectiveFullScreenViewport(); + + if (Renderer->GetScreenWidth() < Renderer->GetScreenHeight()) + { + Renderer->SetMatrixWidth(480); + Renderer->SetMatrixHeight(800); + } + + Renderer->PushPerspectiveProjectionMatrix(pi/6, Renderer->GetMatrixWidth() / Renderer->GetMatrixHeight(), 1.f, 400.f); + + *Console<<"Inner init end!\n"; + + m2.unlock(); +} + + + +void TAndroidApplication::InnerDeinit() +{ + m2.lock(); + Inited = false; + Loaded = false; + + makeShot = true; + LoadingQueue.clear(); + + if (LiteModel != NULL) + { + LiteModel->FreeModel(); + delete LiteModel; + LiteModel = NULL; + } + + IceModel.clear(); + + SimpleLand = std::shared_ptr(); + SimpleLandInv = std::shared_ptr(); + m2.unlock(); +} + + +void TAndroidApplication::InnerDraw() +{ + m2.lock(); + if (!Loaded) + { + glClearColor(0.f, 0.f, 0.f, 1.0f); + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + glBindTexture(GL_TEXTURE_2D, ResourceManager->TexList["ScreenshotTexture"]); + Renderer->PushProjectionMatrix(1,1); + Renderer->LoadIdentity(); + Renderer->DrawRect(vec2(0, 0), vec2(1.f, 1.f)); + Renderer->PopProjectionMatrix(); + + } + else + { + + + DrawAllScene(true); + + if (makeShot) + { + makeShot = false; + + Renderer->SwitchToFrameBuffer("ScreenshotFrame"); + + DrawAllScene(false); + + ResourceManager->TexList.SaveTexDataToPlainBmpToUserData("file.bmp", ResourceManager->FrameManager.ReadFromBufferToTexData("ScreenshotFrame")); + + Renderer->SwitchToScreen(); + + } + } + m2.unlock(); + +} + + +void TAndroidApplication::InnerUpdate(cardinal dt) +{ + + if (!Loaded) + { + + boost::apply_visitor( LoadingQueueVisitor(), *LoadingQueue.begin() ); + LoadingQueue.erase(LoadingQueue.begin()); + + if (LoadingQueue.size() == 0) + { + Loaded = true; + } + } + else + { + + + if (WaveDir) + { + WaterTimer += dt/1000.f; + if (WaterTimer >= 10 * pi) + { + WaveDir = false; + WaterTimer = 10 * pi; + } + } + else + { + WaterTimer -= dt/1000.f; + if (WaterTimer < 0) + { + WaveDir = true; + WaterTimer = 0; + } + } + + CloudTimer += dt / 60000.f; + + while (CloudTimer >= 1.f) + { + CloudTimer -= 1.f; + } + + + SnowTimer += dt/3000.f; + + while (SnowTimer > 10.f) + { + SnowTimer -= 10.f; + } + } + +} + +void TAndroidApplication::InnerOnMove(vec2 shift) +{ + + shift = vec2(shift.v[0]*Renderer->GetMatrixWidth()/static_cast(Renderer->GetScreenWidth()), shift.v[1]*Renderer->GetMatrixHeight()/static_cast(Renderer->GetScreenHeight())); + + boost::get(Renderer->Camera).MoveAlpha(-pi*shift.v[0]*0.1f); +} + +void TAndroidApplication::OnMouseDown(TMouseState& mouseState) +{ + +} \ No newline at end of file diff --git a/jni/main_code.h b/jni/main_code.h new file mode 100644 index 0000000..71494fc --- /dev/null +++ b/jni/main_code.h @@ -0,0 +1,90 @@ +#ifndef GL_CODE_H_INCLUDED +#define GL_CODE_H_INCLUDED + +#ifdef TARGET_ANDROID +//#include "android_api.h" +#endif + +#include +#include +#include + +#ifdef TARGET_ANDROID +#include +#include +#include +#endif + +#include "boost/shared_ptr.hpp" +#include "boost/thread/thread.hpp" +#include "boost/asio.hpp" +#include "boost/signal.hpp" +#include "boost/assign.hpp" +#include "boost/variant.hpp" +#include "boost/function.hpp" +#include "boost/bind.hpp" + +#include "include/Engine.h" + +using namespace SE; + +class TAndroidApplication : public TApplication, public TSerializeInterface +{ +protected: + + void LoadModels(); + void AddFrameBuffers(); + +public: + bool Inited; + bool Loaded; + + std::vector, boost::function, boost::function > > LoadingQueue; + + TLiteModel* LiteModel; + + float WaterTimer; + float SnowTimer; + float CloudTimer; + float SkyTexShift; + bool WaveDir; + + std::vector IceModel; + + std::shared_ptr SimpleLand; + + std::shared_ptr SimpleLandInv; + + TAndroidApplication(); + + virtual void InnerInit(); + + virtual void InnerDeinit(); + + virtual void InnerDraw(); + + virtual void InnerUpdate(cardinal dt); + + virtual void InnerOnMove(vec2 shift); + + virtual void OnMouseDown(TMouseState& mouseState); + + bool IsInited() { return Inited; } + + void DrawSceneWithoutWater(bool inv); + void DrawSnow(); + void DrawAllScene(bool toScreen); + + + virtual void Serialize(boost::property_tree::ptree& propertyTree); + + //void DrawSceneWithoutWaterFrame(); + + +}; + + +//static void checkGlError(const std::string& op); + + +#endif diff --git a/res/drawable-hdpi/icon.png b/res/drawable-hdpi/icon.png new file mode 100644 index 0000000..2bbe589 Binary files /dev/null and b/res/drawable-hdpi/icon.png differ diff --git a/res/drawable-ldpi/icon.png b/res/drawable-ldpi/icon.png new file mode 100644 index 0000000..22734b4 Binary files /dev/null and b/res/drawable-ldpi/icon.png differ diff --git a/res/drawable-mdpi/icon.png b/res/drawable-mdpi/icon.png new file mode 100644 index 0000000..96b1bfc Binary files /dev/null and b/res/drawable-mdpi/icon.png differ diff --git a/res/drawable/notificon.png b/res/drawable/notificon.png new file mode 100644 index 0000000..656209b Binary files /dev/null and b/res/drawable/notificon.png differ diff --git a/res/drawable/thumb.jpg b/res/drawable/thumb.jpg new file mode 100644 index 0000000..cfe281b Binary files /dev/null and b/res/drawable/thumb.jpg differ diff --git a/res/layout/main.xml b/res/layout/main.xml new file mode 100644 index 0000000..4361cfe --- /dev/null +++ b/res/layout/main.xml @@ -0,0 +1,7 @@ + + + diff --git a/res/layout/prefliste.xml b/res/layout/prefliste.xml new file mode 100644 index 0000000..92fd874 --- /dev/null +++ b/res/layout/prefliste.xml @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml new file mode 100644 index 0000000..6a90768 --- /dev/null +++ b/res/values-cs/strings.xml @@ -0,0 +1,22 @@ + + + Horská odražené + Horská odráží ve vodě, s účinkem sněhu + Pokud dojde k chybě aplikace, prosím, kontaktujte mě: mephi1984@gmail.com + + Sněžení + Sněžení je zapnuta + Sněžení je vypnutý + + Denní čas + Vyberte si čas dne + + + + Den + Přeháňky den + Noc + + + + diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml new file mode 100644 index 0000000..0710fac --- /dev/null +++ b/res/values-de/strings.xml @@ -0,0 +1,22 @@ + + + Reflektierte Berg + Berg spiegelt sich im Wasser, mit dem Effekt der Schnee + Wenn die Anwendung abstürzt, bitte kontaktieren Sie mich: mephi1984@gmail.com + + Schneefall + Schneefall ist eingeschaltet + Schneefall ausgeschaltet + + Zeit des Tages + Wählen Sie die Zeit des Tages + + + Day + Bewölkten Day + Night + + + + + diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml new file mode 100644 index 0000000..655713d --- /dev/null +++ b/res/values-es/strings.xml @@ -0,0 +1,23 @@ + + + Montaña que se refleja + Montaña que se refleja en el agua con efectos nevada + Si la aplicación se bloquea, por favor póngase en contacto conmigo: mephi1984@gmail.com + + Las nevadas + Las nevadas se enciende + Las nevadas se apaga + + La hora del día + Elija la hora del día + + + + Día + Día nublado + Noche + + + + + diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml new file mode 100644 index 0000000..72f228d --- /dev/null +++ b/res/values-fr/strings.xml @@ -0,0 +1,22 @@ + + + Montagne réfléchie + Montagne reflète dans l\'eau avec des effets des chutes de neige + Si l\'application se bloque, s\'il vous plaît contactez-moi : mephi1984@gmail.com + + Chutes de neige + Chutes de neige est en marche + Chutes de neige est éteint + + L\'heure du jour + Choisissez le moment de la journée + + + Jour + Temps nuageux + Nuit + + + + + diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml new file mode 100644 index 0000000..50457f6 --- /dev/null +++ b/res/values-it/strings.xml @@ -0,0 +1,30 @@ + + + Montagna riflessa + Montagna riflessa nell\'acqua, con l\'effetto di neve + Se l\'applicazione si blocca, si prega di contattare me: mephi1984@gmail.com + + Nevicate + Nevicate si accende + Nevicata è spento + + Il momento della giornata + Scegliere il momento della giornata + + + + + Giorno + Giornata nuvolosa + Notte + + + + + 0 + 1 + 2 + + + + diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml new file mode 100644 index 0000000..2f86135 --- /dev/null +++ b/res/values-nl/strings.xml @@ -0,0 +1,22 @@ + + + Reflected berg + Mountain weerspiegeld in het water met sneeuwval effecten + Als de toepassing crasht, neem dan contact met mij op: mephi1984@gmail.com + + Sneeuwval + Sneeuwval is ingeschakeld + Sneeuwval is uitgeschakeld + + Tijd van de dag + Kies de tijd van de dag + + + Dag + Bewolkte dag + Nacht + + + + + diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml new file mode 100644 index 0000000..968486c --- /dev/null +++ b/res/values-pt/strings.xml @@ -0,0 +1,23 @@ + + + Montanha refletidas + Montanha refletida na água com efeitos queda de neve + Se o aplicativo falha, por favor contacte-me: mephi1984@gmail.com + + Queda de neve + Neve está ligado + Neve está desligado + + Hora do dia + Escolha a hora do dia + + + + Dia + Dia nublado + Noite + + + + + diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml new file mode 100644 index 0000000..eccfb46 --- /dev/null +++ b/res/values-ru/strings.xml @@ -0,0 +1,23 @@ + + + Отраженная гора + Гора, отраженная в воде, с эффектом снегопада + Если приложение падает, пожалуйста, свяжитесь со мною: mephi1984@gmail.com + + Снегопад + Снегопад включен + Снегопад выключен + + Время суток + Выберите время суток + + + + День + Облачный день + Ночь + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml new file mode 100644 index 0000000..162ccbd --- /dev/null +++ b/res/values/strings.xml @@ -0,0 +1,43 @@ + + + Reflected mountain + Mountain reflected in the water with snow effects + If wallpaper crashes or something else goes wrong, please, contact with me: mephi1984@gmail.com + + Snow + Snow is on + Snow is off + + Time of day + Choose time of day to display + + + + + + + + + + + + + + + Day + Cloudy day + Night + + + + + 0 + 1 + 2 + + + + diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml new file mode 100644 index 0000000..4917e51 --- /dev/null +++ b/res/xml/preferences.xml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/res/xml/wallpaper.xml b/res/xml/wallpaper.xml new file mode 100644 index 0000000..0a9c5da --- /dev/null +++ b/res/xml/wallpaper.xml @@ -0,0 +1,6 @@ + + \ No newline at end of file diff --git a/src/fishrungames/mountainwallpaper/GLWallpaperService.java b/src/fishrungames/mountainwallpaper/GLWallpaperService.java new file mode 100644 index 0000000..e872099 --- /dev/null +++ b/src/fishrungames/mountainwallpaper/GLWallpaperService.java @@ -0,0 +1,960 @@ +package fishrungames.mountainwallpaper; + + +import fishrungames.mountainwallpaper.BaseConfigChooser.ComponentSizeChooser; +import fishrungames.mountainwallpaper.BaseConfigChooser.SimpleEGLConfigChooser; + +import java.util.ArrayList; +import java.util.Calendar; + +import javax.microedition.khronos.egl.EGL10; +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.egl.EGLContext; +import javax.microedition.khronos.egl.EGLDisplay; +import javax.microedition.khronos.egl.EGLSurface; + + +import android.service.wallpaper.WallpaperService; +import android.util.Log; +import android.view.SurfaceHolder; + +import fishrungames.engine.EngineWrapper; + + +public class GLWallpaperService extends WallpaperService { + private static final String TAG = "GLWallpaperService"; + + @Override + public Engine onCreateEngine() { + return new GLEngine(); + } + + public class GLEngine extends Engine { + public final static int RENDERMODE_WHEN_DIRTY = 0; + public final static int RENDERMODE_CONTINUOUSLY = 1; + + private GLThread mGLThread; + private EGLConfigChooser mEGLConfigChooser; + private EGLContextFactory mEGLContextFactory; + private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory; + + private int mDebugFlags; + + public GLEngine() { + super(); + } + + @Override + public void onVisibilityChanged(boolean visible) { + if (visible) { + onResume(); + } else { + onPause(); + } + super.onVisibilityChanged(visible); + } + + @Override + public void onCreate(SurfaceHolder surfaceHolder) { + super.onCreate(surfaceHolder); + // Log.d(TAG, "GLEngine.onCreate()"); + } + + @Override + public void onDestroy() { + super.onDestroy(); + // Log.d(TAG, "GLEngine.onDestroy()"); + mGLThread.requestExitAndWait(); + } + + @Override + public void onSurfaceChanged(SurfaceHolder holder, int format, + int width, int height) { + // Log.d(TAG, "onSurfaceChanged()"); + + + + mGLThread.onWindowResize(width, height); + + super.onSurfaceChanged(holder, format, width, height); + } + + @Override + public void onSurfaceCreated(SurfaceHolder holder) { + Log.d(TAG, "onSurfaceCreated()"); + mGLThread.surfaceCreated(holder); + super.onSurfaceCreated(holder); + } + + @Override + public void onSurfaceDestroyed(SurfaceHolder holder) { + Log.d(TAG, "onSurfaceDestroyed()"); + mGLThread.surfaceDestroyed(); + super.onSurfaceDestroyed(holder); + } + + + public void setDebugFlags(int debugFlags) { + mDebugFlags = debugFlags; + } + + public int getDebugFlags() { + return mDebugFlags; + } + + public void setRenderer() { + checkRenderThreadState(); + if (mEGLConfigChooser == null) { + mEGLConfigChooser = new SimpleEGLConfigChooser(true); + } + if (mEGLContextFactory == null) { + //mEGLContextFactory = new DefaultContextFactory(); + mEGLContextFactory = new ES20ContextFactory(); + } + if (mEGLWindowSurfaceFactory == null) { + mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory(); + } + mGLThread = new GLThread(mEGLConfigChooser, + mEGLContextFactory, mEGLWindowSurfaceFactory); + mGLThread.start(); + } + + public void setEGLContextFactory(EGLContextFactory factory) { + checkRenderThreadState(); + mEGLContextFactory = factory; + } + + public void setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory factory) { + checkRenderThreadState(); + mEGLWindowSurfaceFactory = factory; + } + + public void setEGLConfigChooser(EGLConfigChooser configChooser) { + checkRenderThreadState(); + mEGLConfigChooser = configChooser; + } + + public void setEGLConfigChooser(boolean needDepth) { + setEGLConfigChooser(new SimpleEGLConfigChooser(needDepth)); + } + + public void setEGLConfigChooser(int redSize, int greenSize, + int blueSize, int alphaSize, int depthSize, int stencilSize) { + setEGLConfigChooser(new ComponentSizeChooser(redSize, greenSize, + blueSize, alphaSize, depthSize, stencilSize)); + } + + public void setRenderMode(int renderMode) { + mGLThread.setRenderMode(renderMode); + } + + public int getRenderMode() { + return mGLThread.getRenderMode(); + } + + public void requestRender() { + mGLThread.requestRender(); + } + + public void onPause() { + mGLThread.onPause(); + } + + public void onResume() { + mGLThread.onResume(); + } + + public void queueEvent(Runnable r) { + mGLThread.queueEvent(r); + } + + private void checkRenderThreadState() { + if (mGLThread != null) { + throw new IllegalStateException( + "setRenderer has already been called for this instance."); + } + } + } +} + + +// ---------------------------------------------------------------------- + +/** + * An interface for customizing the eglCreateContext and eglDestroyContext + * calls. + * + * + * This interface must be implemented by clients wishing to call + * {@link GLWallpaperService#setEGLContextFactory(EGLContextFactory)} + */ +interface EGLContextFactory { + EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig); + + void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context); +} + +class DefaultContextFactory implements EGLContextFactory { + + public EGLContext createContext(EGL10 egl, EGLDisplay display, + EGLConfig config) { + return egl + .eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, null); + } + + public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) { + egl.eglDestroyContext(display, context); + } +} + + +class ES20ContextFactory implements EGLContextFactory { + + private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098; + + public EGLContext createContext(EGL10 egl, EGLDisplay display, + EGLConfig config) { + + + int[] attrib_list = + { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE }; + + return egl + .eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, attrib_list); + } + + public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) { + egl.eglDestroyContext(display, context); + } +} + +/** + * An interface for customizing the eglCreateWindowSurface and eglDestroySurface + * calls. + * + * + * This interface must be implemented by clients wishing to call + * {@link GLWallpaperService#setEGLWindowSurfaceFactory(EGLWindowSurfaceFactory)} + */ +interface EGLWindowSurfaceFactory { + EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, + EGLConfig config, Object nativeWindow); + + void destroySurface(EGL10 egl, EGLDisplay display, EGLSurface surface); +} + +class DefaultWindowSurfaceFactory implements EGLWindowSurfaceFactory { + + public EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display, + EGLConfig config, Object nativeWindow) { + // this is a bit of a hack to work around Droid init problems - if you + // don't have this, it'll get hung up on orientation changes + EGLSurface eglSurface = null; + while (eglSurface == null) { + try { + eglSurface = egl.eglCreateWindowSurface(display, config, + nativeWindow, null); + } catch (Throwable t) { + } finally { + if (eglSurface == null) { + try { + Thread.sleep(10); + } catch (InterruptedException t) { + } + } + } + } + return eglSurface; + } + + public void destroySurface(EGL10 egl, EGLDisplay display, EGLSurface surface) { + egl.eglDestroySurface(display, surface); + } +} + + +class EglHelper { + + private EGL10 mEgl; + private EGLDisplay mEglDisplay; + private EGLSurface mEglSurface; + private EGLContext mEglContext; + EGLConfig mEglConfig; + + private EGLConfigChooser mEGLConfigChooser; + private EGLContextFactory mEGLContextFactory; + private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory; + + + public EglHelper(EGLConfigChooser chooser, + EGLContextFactory contextFactory, + EGLWindowSurfaceFactory surfaceFactory) { + this.mEGLConfigChooser = chooser; + this.mEGLContextFactory = contextFactory; + this.mEGLWindowSurfaceFactory = surfaceFactory; + + } + + /** + * Initialize EGL for a given configuration spec. + * + * @param configSpec + */ + public void start() { + String instanceId = ""; + Log.d("EglHelper" + instanceId, "start()"); + if (mEgl == null) { + Log.d("EglHelper" + instanceId, "getting new EGL"); + /* + * Get an EGL instance + */ + mEgl = (EGL10) EGLContext.getEGL(); + } else { + Log.d("EglHelper" + instanceId, "reusing EGL"); + } + + if (mEglDisplay == null) { + Log.d("EglHelper" + instanceId, "getting new display"); + /* + * Get to the default display. + */ + mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); + } else { + Log.d("EglHelper" + instanceId, "reusing display"); + } + + if (mEglConfig == null) { + Log.d("EglHelper" + instanceId, "getting new config"); + /* + * We can now initialize EGL for that display + */ + int[] version = new int[2]; + mEgl.eglInitialize(mEglDisplay, version); + mEglConfig = mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay); + } else { + Log.d("EglHelper" + instanceId, "reusing config"); + } + + if (mEglContext == null) { + Log.d("EglHelper" + instanceId, "creating new context"); + /* + * Create an OpenGL ES context. This must be done only once, an + * OpenGL context is a somewhat heavy object. + */ + mEglContext = mEGLContextFactory.createContext(mEgl, mEglDisplay, + mEglConfig); + if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) { + throw new RuntimeException("createContext failed"); + } + } else { + Log.d("EglHelper" + instanceId, "reusing context"); + } + + mEglSurface = null; + } + + /* + * React to the creation of a new surface by creating and returning an + * OpenGL interface that renders to that surface. + */ + + + public void createSurface(SurfaceHolder holder) { + + if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) { + + + mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, + EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); + mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, + mEglSurface); + } + + + mEglSurface = mEGLWindowSurfaceFactory.createWindowSurface(mEgl, + mEglDisplay, mEglConfig, holder); + + if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { + throw new RuntimeException("createWindowSurface failed"); + } + + + if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, + mEglContext)) { + //throw new RuntimeException("eglMakeCurrent failed."); + } + + + } + + /** + * Display the current render surface. + * + * @return false if the context has been lost. + */ + public boolean swap() { + try { + mEgl.eglSwapBuffers(mEglDisplay, mEglSurface); + } catch (Exception e) { + return false; + } + + return true; + + + /* + * Always check for EGL_CONTEXT_LOST, which means the context and all + * associated data were lost (For instance because the device went to + * sleep). We need to sleep until we get a new surface. + */ + + } + + public void destroySurface() { + if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) { + mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, + EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); + mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, + mEglSurface); + mEglSurface = null; + } + } + + public void finish() { + if (mEglContext != null) { + mEGLContextFactory.destroyContext(mEgl, mEglDisplay, mEglContext); + mEglContext = null; + } + if (mEglDisplay != null) { + mEgl.eglTerminate(mEglDisplay); + mEglDisplay = null; + } + } +} + +class GLThread extends Thread { + private final static boolean LOG_THREADS = false; + public final static int DEBUG_CHECK_GL_ERROR = 1; + public final static int DEBUG_LOG_GL_CALLS = 2; + + private final GLThreadManager sGLThreadManager = new GLThreadManager(); + private GLThread mEglOwner; + + private EGLConfigChooser mEGLConfigChooser; + private EGLContextFactory mEGLContextFactory; + private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory; + + + public SurfaceHolder mHolder; + private boolean mSizeChanged = true; + + // Once the thread is started, all accesses to the following member + // variables are protected by the sGLThreadManager monitor + public boolean mDone; + private boolean mPaused; + private boolean mHasSurface; + private boolean mWaitingForSurface; + private boolean mHaveEgl; + private int mWidth; + private int mHeight; + private int mRenderMode; + private boolean mRequestRender; + private boolean mEventsWaiting; + // End of member variables protected by the sGLThreadManager monitor. + + //private GLWallpaperService.Renderer mRenderer; + + private ArrayList mEventQueue = new ArrayList(); + private EglHelper mEglHelper; + + + static long lastTimeStamp; + static boolean gameIsInited = false; + + GLThread(EGLConfigChooser chooser, + EGLContextFactory contextFactory, + EGLWindowSurfaceFactory surfaceFactory) { + super(); + mDone = false; + mWidth = 0; + mHeight = 0; + mRequestRender = true; + mRenderMode = GLWallpaperService.GLEngine.RENDERMODE_CONTINUOUSLY; + + this.mEGLConfigChooser = chooser; + this.mEGLContextFactory = contextFactory; + this.mEGLWindowSurfaceFactory = surfaceFactory; + + Calendar c = Calendar.getInstance(); + lastTimeStamp = c.getTimeInMillis(); + gameIsInited = true; + } + + @Override + public void run() { + setName("GLThread " + getId()); + if (LOG_THREADS) { + Log.i("GLThread", "starting tid=" + getId()); + } + + try { + guardedRun(); + } catch (InterruptedException e) { + // fall thru and exit normally + } finally { + sGLThreadManager.threadExiting(this); + } + } + + /* + * This private method should only be called inside a + * synchronized(sGLThreadManager) block. + */ + private void stopEglLocked() { + if (mHaveEgl) { + mHaveEgl = false; + mEglHelper.destroySurface(); + sGLThreadManager.releaseEglSurface(this); + } + } + + private void guardedRun() throws InterruptedException { + mEglHelper = new EglHelper(mEGLConfigChooser, mEGLContextFactory, + mEGLWindowSurfaceFactory/*, mGLWrapper*/); + try { + + boolean tellRendererSurfaceCreated = true; + boolean tellRendererSurfaceChanged = true; + + /* + * This is our main activity thread's loop, we go until asked to + * quit. + */ + while (!isDone()) { + /* + * Update the asynchronous state (window size) + */ + int w = 0; + int h = 0; + boolean changed = false; + boolean needStart = false; + boolean eventsWaiting = false; + + synchronized (sGLThreadManager) { + while (true) { + // Manage acquiring and releasing the SurfaceView + // surface and the EGL surface. + if (mPaused) { + stopEglLocked(); + } + if (!mHasSurface) { + if (!mWaitingForSurface) { + stopEglLocked(); + mWaitingForSurface = true; + sGLThreadManager.notifyAll(); + } + } else { + if (!mHaveEgl) { + if (sGLThreadManager.tryAcquireEglSurface(this)) { + mHaveEgl = true; + mEglHelper.start(); + mRequestRender = true; + needStart = true; + } + } + } + + // Check if we need to wait. If not, update any state + // that needs to be updated, copy any state that + // needs to be copied, and use "break" to exit the + // wait loop. + + if (mDone) { + return; + } + + if (mEventsWaiting) { + eventsWaiting = true; + mEventsWaiting = false; + break; + } + + if ((!mPaused) + && mHasSurface + && mHaveEgl + && (mWidth > 0) + && (mHeight > 0) + && (mRequestRender || (mRenderMode == GLWallpaperService.GLEngine.RENDERMODE_CONTINUOUSLY))) { + changed = mSizeChanged; + w = mWidth; + h = mHeight; + mSizeChanged = false; + mRequestRender = false; + if (mHasSurface && mWaitingForSurface) { + changed = true; + mWaitingForSurface = false; + sGLThreadManager.notifyAll(); + } + break; + } + + + + // By design, this is the only place where we wait(). + + if (LOG_THREADS) { + Log.i("GLThread", "waiting tid=" + getId()); + } + sGLThreadManager.wait(); + } + } // end of synchronized(sGLThreadManager) + + /* + * Handle queued events + */ + if (eventsWaiting) { + Runnable r; + while ((r = getEvent()) != null) { + r.run(); + if (isDone()) { + return; + } + } + // Go back and see if we need to wait to render. + continue; + } + + if (needStart) { + tellRendererSurfaceCreated = true; + changed = true; + } + if (changed) { + mEglHelper.createSurface(mHolder); + tellRendererSurfaceChanged = true; + } + if (tellRendererSurfaceCreated) { + + tellRendererSurfaceCreated = false; + } + + if (tellRendererSurfaceChanged) { + + + //Xperimental -- VLAD KHOREV + JniWrapper.Init(w, h); + + tellRendererSurfaceChanged = false; + } + + + if ((w > 0) && (h > 0)) { + /* draw a frame here */ + + if (gameIsInited) + { + Calendar c = Calendar.getInstance(); + + long currentTimeStamp = c.getTimeInMillis(); + + EngineWrapper.Update(currentTimeStamp - lastTimeStamp); + + lastTimeStamp = currentTimeStamp; + + } + + /* + * Once we're done with GL, we need to call swapBuffers() to + * instruct the system to display the rendered frame + */ + mEglHelper.swap(); + } + } + } finally { + /* + * clean-up everything... + */ + synchronized (sGLThreadManager) { + stopEglLocked(); + mEglHelper.finish(); + } + } + } + + private boolean isDone() { + synchronized (sGLThreadManager) { + return mDone; + } + } + + public void setRenderMode(int renderMode) { + if (!((GLWallpaperService.GLEngine.RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= GLWallpaperService.GLEngine.RENDERMODE_CONTINUOUSLY))) { + throw new IllegalArgumentException("renderMode"); + } + synchronized (sGLThreadManager) { + mRenderMode = renderMode; + if (renderMode == GLWallpaperService.GLEngine.RENDERMODE_CONTINUOUSLY) { + sGLThreadManager.notifyAll(); + } + } + } + + public int getRenderMode() { + synchronized (sGLThreadManager) { + return mRenderMode; + } + } + + public void requestRender() { + synchronized (sGLThreadManager) { + mRequestRender = true; + sGLThreadManager.notifyAll(); + } + } + + public void surfaceCreated(SurfaceHolder holder) { + mHolder = holder; + synchronized (sGLThreadManager) { + if (LOG_THREADS) { + Log.i("GLThread", "surfaceCreated tid=" + getId()); + } + mHasSurface = true; + sGLThreadManager.notifyAll(); + } + } + + public void surfaceDestroyed() { + synchronized (sGLThreadManager) { + if (LOG_THREADS) { + Log.i("GLThread", "surfaceDestroyed tid=" + getId()); + } + mHasSurface = false; + sGLThreadManager.notifyAll(); + while (!mWaitingForSurface && isAlive() && !mDone) { + try { + sGLThreadManager.wait(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } + } + + public void onPause() { + synchronized (sGLThreadManager) { + mPaused = true; + sGLThreadManager.notifyAll(); + } + } + + public void onResume() { + synchronized (sGLThreadManager) { + mPaused = false; + mRequestRender = true; + sGLThreadManager.notifyAll(); + } + } + + public void onWindowResize(int w, int h) { + synchronized (sGLThreadManager) { + mWidth = w; + mHeight = h; + mSizeChanged = true; + sGLThreadManager.notifyAll(); + } + } + + public void requestExitAndWait() { + // don't call this from GLThread thread or it is a guaranteed + // deadlock! + synchronized (sGLThreadManager) { + mDone = true; + sGLThreadManager.notifyAll(); + } + try { + join(); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } + } + + /** + * Queue an "event" to be run on the GL rendering thread. + * + * @param r + * the runnable to be run on the GL rendering thread. + */ + public void queueEvent(Runnable r) { + synchronized (this) { + mEventQueue.add(r); + synchronized (sGLThreadManager) { + mEventsWaiting = true; + sGLThreadManager.notifyAll(); + } + } + } + + private Runnable getEvent() { + synchronized (this) { + if (mEventQueue.size() > 0) { + return (Runnable) mEventQueue.remove(0); + } + + } + return null; + } + + private class GLThreadManager { + + public synchronized void threadExiting(GLThread thread) { + if (LOG_THREADS) { + Log.i("GLThread", "exiting tid=" + thread.getId()); + } + thread.mDone = true; + if (mEglOwner == thread) { + mEglOwner = null; + } + notifyAll(); + } + + /* + * Tries once to acquire the right to use an EGL surface. Does not + * block. + * + * @return true if the right to use an EGL surface was acquired. + */ + public synchronized boolean tryAcquireEglSurface(GLThread thread) { + if (mEglOwner == thread || mEglOwner == null) { + mEglOwner = thread; + notifyAll(); + return true; + } + return false; + } + + public synchronized void releaseEglSurface(GLThread thread) { + if (mEglOwner == thread) { + mEglOwner = null; + } + notifyAll(); + } + } +} + +interface EGLConfigChooser { + EGLConfig chooseConfig(EGL10 egl, EGLDisplay display); +} + +abstract class BaseConfigChooser implements EGLConfigChooser { + public BaseConfigChooser(int[] configSpec) { + mConfigSpec = configSpec; + } + + public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { + int[] num_config = new int[1]; + egl.eglChooseConfig(display, mConfigSpec, null, 0, num_config); + + int numConfigs = num_config[0]; + + if (numConfigs <= 0) { + throw new IllegalArgumentException("No configs match configSpec"); + } + + EGLConfig[] configs = new EGLConfig[numConfigs]; + egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs, + num_config); + EGLConfig config = chooseConfig(egl, display, configs); + if (config == null) { + throw new IllegalArgumentException("No config chosen"); + } + return config; + } + + abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, + EGLConfig[] configs); + + protected int[] mConfigSpec; + + public static class ComponentSizeChooser extends BaseConfigChooser { + public ComponentSizeChooser(int redSize, int greenSize, int blueSize, + int alphaSize, int depthSize, int stencilSize) { + super(new int[] { EGL10.EGL_RED_SIZE, redSize, + EGL10.EGL_GREEN_SIZE, greenSize, EGL10.EGL_BLUE_SIZE, + blueSize, EGL10.EGL_ALPHA_SIZE, alphaSize, + EGL10.EGL_DEPTH_SIZE, depthSize, EGL10.EGL_STENCIL_SIZE, + stencilSize, EGL10.EGL_NONE }); + mValue = new int[1]; + mRedSize = redSize; + mGreenSize = greenSize; + mBlueSize = blueSize; + mAlphaSize = alphaSize; + mDepthSize = depthSize; + mStencilSize = stencilSize; + } + + @Override + public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, + EGLConfig[] configs) { + EGLConfig closestConfig = null; + int closestDistance = 1000; + for (EGLConfig config : configs) { + int d = findConfigAttrib(egl, display, config, + EGL10.EGL_DEPTH_SIZE, 0); + int s = findConfigAttrib(egl, display, config, + EGL10.EGL_STENCIL_SIZE, 0); + if (d >= mDepthSize && s >= mStencilSize) { + int r = findConfigAttrib(egl, display, config, + EGL10.EGL_RED_SIZE, 0); + int g = findConfigAttrib(egl, display, config, + EGL10.EGL_GREEN_SIZE, 0); + int b = findConfigAttrib(egl, display, config, + EGL10.EGL_BLUE_SIZE, 0); + int a = findConfigAttrib(egl, display, config, + EGL10.EGL_ALPHA_SIZE, 0); + int distance = Math.abs(r - mRedSize) + + Math.abs(g - mGreenSize) + + Math.abs(b - mBlueSize) + + Math.abs(a - mAlphaSize); + if (distance < closestDistance) { + closestDistance = distance; + closestConfig = config; + } + } + } + return closestConfig; + } + + private int findConfigAttrib(EGL10 egl, EGLDisplay display, + EGLConfig config, int attribute, int defaultValue) { + + if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) { + return mValue[0]; + } + return defaultValue; + } + + private int[] mValue; + // Subclasses can adjust these values: + protected int mRedSize; + protected int mGreenSize; + protected int mBlueSize; + protected int mAlphaSize; + protected int mDepthSize; + protected int mStencilSize; + } + + /** + * This class will choose a supported surface as close to RGB565 as + * possible, with or without a depth buffer. + * + */ + public static class SimpleEGLConfigChooser extends ComponentSizeChooser { + public SimpleEGLConfigChooser(boolean withDepthBuffer) { + super(4, 4, 4, 0, withDepthBuffer ? 16 : 0, 0); + // Adjust target values. This way we'll accept a 4444 or + // 555 buffer if there's no 565 buffer available. + mRedSize = 5; + mGreenSize = 6; + mBlueSize = 5; + } + } +} diff --git a/src/fishrungames/mountainwallpaper/JniWrapper.java b/src/fishrungames/mountainwallpaper/JniWrapper.java new file mode 100644 index 0000000..7454035 --- /dev/null +++ b/src/fishrungames/mountainwallpaper/JniWrapper.java @@ -0,0 +1,27 @@ +package fishrungames.mountainwallpaper; + +public class JniWrapper +{ + + static + { + System.loadLibrary("SalmonWallpaper"); + } + + public static void LoadLibrary() + { + //To force loading libraries + } + + public static native void SetTimeOfDayPref(int timeofday); + + public static native void SetSnowPref(boolean snow); + + + public static native void Init(int width, int height); + + public static native void SetOffset(float offsetX, float offsetY); + + public static native void SetOrientation(int isLandscape); + +} diff --git a/src/fishrungames/mountainwallpaper/MountainWallpaperService.java b/src/fishrungames/mountainwallpaper/MountainWallpaperService.java new file mode 100644 index 0000000..5b4139b --- /dev/null +++ b/src/fishrungames/mountainwallpaper/MountainWallpaperService.java @@ -0,0 +1,233 @@ +package fishrungames.mountainwallpaper; + + +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; + +import android.net.ConnectivityManager; + +import android.os.Handler; +import android.preference.PreferenceManager; + +import android.view.MotionEvent; +import android.view.SurfaceHolder; + +//import com.seb.SLWP.SLWP.GlEngine.DownloadTask; + +import fishrungames.engine.EngineWrapper; + +public class MountainWallpaperService extends GLWallpaperService implements + OnSharedPreferenceChangeListener { + /* + * (non-Javadoc) + * + * @see android.app.Service#onLowMemory() + */ + static + { + EngineWrapper.LoadSalmonEngineLibrary(); + JniWrapper.LoadLibrary(); + } + + + public static final long SLEEPTIME = 1000 * 60 * 30; // 30 minutes + private GlEngine mGle; + + public static Context mContext; + public static boolean ShowClouds; + public static boolean TouchRot; + + public static int Bg; + public static boolean Usebg; + public static int Tex; + + static long Synctime; + + public boolean Slidedir; + public boolean Slideplanet; + public boolean Syncrot; + public static boolean Randomtex = true; + public static boolean visible = false; + + public static boolean useCropper = true; + public static int Cropaspect; + public static boolean loading = false; + + public static final Handler mHandler = new Handler(); + public static final int RNDMAP = -1; + public static boolean destroyed; + public static String bgfile; + public ConnectivityManager cm; + public boolean needresume; + public boolean fstart; + public static String[] randlist; + public int curtexidx = -99; + + static final String ACTION_FOREGROUND = "fishrungames.mountainwallpaper.FOREGROUND"; + static final String ACTION_BACKGROUND = "fishrungames.mountainwallpaper.BACKGROUND"; + + + + @Override + public void onCreate() { + // TODO Auto-generated method stub + super.onCreate(); + + + PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this); + + EngineWrapper.SetActivityInstance(this); + EngineWrapper.SetupEnviroment(); + + String apkFilePath = null; + ApplicationInfo appInfo = null; + PackageManager packMgmr = this.getPackageManager(); + try { + appInfo = packMgmr.getApplicationInfo("fishrungames.mountainwallpaper", 0); + } catch (NameNotFoundException e) { + + + + e.printStackTrace(); + throw new RuntimeException("Unable to locate assets, aborting..."); + } + apkFilePath = appInfo.sourceDir; + + EngineWrapper.SetupApkFilePath(apkFilePath); + + Init(); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + // handleCommand(intent); + // We want this service to continue running until it is explicitly + // stopped, so return sticky. + return START_STICKY; + } + + private void Init() { + try { + mContext = this; + cm = (ConnectivityManager) mContext + .getSystemService(Context.CONNECTIVITY_SERVICE); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void onDestroy() { + // TODO Auto-generated method stub + super.onDestroy(); + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, + String key) { + + if (key.compareToIgnoreCase("Timeofday") == 0) + { + int time = Integer.parseInt(sharedPreferences.getString("Timeofday", "0")); + JniWrapper.SetTimeOfDayPref(time); + } + + if (key.compareToIgnoreCase("Snow") == 0) { + + JniWrapper.SetSnowPref(sharedPreferences.getBoolean("Snow", false)); + + } + } + + @Override + public Engine onCreateEngine() { + if (mGle != null) { + mGle = null; + } + try { + + mGle = new GlEngine(); + + } catch (Exception e) { + return null; + } + + return mGle; + } + + class GlEngine extends GLEngine { + + public Handler mHandler = new Handler(); + + long NOW; + + @Override + public void onCreate(SurfaceHolder surfaceHolder) { + super.onCreate(surfaceHolder); + try { + this.setTouchEventsEnabled(true); + fstart = true; + setRenderer(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void onTouchEvent(MotionEvent e) { + + return; + } + + @Override + public void onOffsetsChanged(float xOffset, float yOffset, + float xOffsetStep, float yOffsetStep, int xPixelOffset, + int yPixelOffset) { + + super.onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep, + xPixelOffset, yPixelOffset); + + JniWrapper.SetOffset(xPixelOffset*xOffsetStep, yPixelOffset*yOffsetStep); + + } + + @Override + public void onVisibilityChanged(boolean visible) { + // TODO Auto-generated method stub + super.onVisibilityChanged(visible); + MountainWallpaperService.visible = visible; + if (visible) { + + } else { + + } + } + + @Override + public void onPause() { + super.onPause(); + } + + @Override + public void onResume() { + + super.onResume(); + } + + @Override + public void onSurfaceChanged(SurfaceHolder holder, int format, + int width, int height) { + // TODO Auto-generated method stub + super.onSurfaceChanged(holder, format, width, height); + fstart = true; + } + + } + +} \ No newline at end of file diff --git a/src/fishrungames/mountainwallpaper/Prefs.java b/src/fishrungames/mountainwallpaper/Prefs.java new file mode 100644 index 0000000..0e0c578 --- /dev/null +++ b/src/fishrungames/mountainwallpaper/Prefs.java @@ -0,0 +1,72 @@ +package fishrungames.mountainwallpaper; + +import fishrungames.mountainwallpaper.R; +import fishrungames.mountainwallpaper.JniWrapper; + + +import android.content.Intent; + +import android.net.Uri; +import android.os.Bundle; +import android.preference.CheckBoxPreference; +import android.preference.ListPreference; +import android.preference.Preference; +import android.preference.PreferenceActivity; + +import android.preference.Preference.OnPreferenceChangeListener; + + +public class Prefs extends PreferenceActivity implements + OnPreferenceChangeListener { + + + private CheckBoxPreference snowPref; + private ListPreference timeOfDayPref; + + + public static Uri currImageURI; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.prefliste); + addPreferencesFromResource(R.xml.preferences); + + + snowPref = (CheckBoxPreference)this.getPreferenceManager().findPreference("Snow"); + timeOfDayPref = (ListPreference) findPreference("Timeofday"); + + if (timeOfDayPref.getKey().compareToIgnoreCase("Timeofday") == 0) + { + JniWrapper.SetTimeOfDayPref(Integer.parseInt((String) timeOfDayPref.getValue())); + + } + + if (snowPref.getKey().compareToIgnoreCase("Snow") == 0) { + if (!snowPref.isChecked()) + { + JniWrapper.SetSnowPref(false); + } + else + { + JniWrapper.SetSnowPref(true); + } + } + + } + + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + + return true; + + } + + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + + } + +} diff --git a/windows/Readme.txt b/windows/Readme.txt new file mode 100644 index 0000000..194ff22 --- /dev/null +++ b/windows/Readme.txt @@ -0,0 +1,5 @@ + : +1) svn -, C:\Work\Salmon Engine\ +1) SalmonEnginePath , c:\Work\Salmon Engine\ +2) - +3) Template.sln Visual C++ 2010 \ No newline at end of file diff --git a/windows/Template.sln b/windows/Template.sln new file mode 100644 index 0000000..5b553f6 --- /dev/null +++ b/windows/Template.sln @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C++ Express 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Template", "Template\Template.vcxproj", "{0080A3E1-DFBF-4557-B198-E6D5D7724393}" + ProjectSection(ProjectDependencies) = postProject + {48ADCE9F-9539-4D3A-BCFA-C2ABABAF0B20} = {48ADCE9F-9539-4D3A-BCFA-C2ABABAF0B20} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Salmon Engine", "..\..\..\Engine\Salmon Engine\Salmon Engine.vcxproj", "{48ADCE9F-9539-4D3A-BCFA-C2ABABAF0B20}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug_nosound|Win32 = Debug_nosound|Win32 + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0080A3E1-DFBF-4557-B198-E6D5D7724393}.Debug_nosound|Win32.ActiveCfg = Debug|Win32 + {0080A3E1-DFBF-4557-B198-E6D5D7724393}.Debug_nosound|Win32.Build.0 = Debug|Win32 + {0080A3E1-DFBF-4557-B198-E6D5D7724393}.Debug|Win32.ActiveCfg = Debug|Win32 + {0080A3E1-DFBF-4557-B198-E6D5D7724393}.Debug|Win32.Build.0 = Debug|Win32 + {0080A3E1-DFBF-4557-B198-E6D5D7724393}.Release|Win32.ActiveCfg = Release|Win32 + {0080A3E1-DFBF-4557-B198-E6D5D7724393}.Release|Win32.Build.0 = Release|Win32 + {48ADCE9F-9539-4D3A-BCFA-C2ABABAF0B20}.Debug_nosound|Win32.ActiveCfg = Debug_nosound|Win32 + {48ADCE9F-9539-4D3A-BCFA-C2ABABAF0B20}.Debug_nosound|Win32.Build.0 = Debug_nosound|Win32 + {48ADCE9F-9539-4D3A-BCFA-C2ABABAF0B20}.Debug|Win32.ActiveCfg = Debug|Win32 + {48ADCE9F-9539-4D3A-BCFA-C2ABABAF0B20}.Debug|Win32.Build.0 = Debug|Win32 + {48ADCE9F-9539-4D3A-BCFA-C2ABABAF0B20}.Release|Win32.ActiveCfg = Release|Win32 + {48ADCE9F-9539-4D3A-BCFA-C2ABABAF0B20}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/windows/Template/Template.vcxproj b/windows/Template/Template.vcxproj new file mode 100644 index 0000000..14c0689 --- /dev/null +++ b/windows/Template/Template.vcxproj @@ -0,0 +1,90 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {0080A3E1-DFBF-4557-B198-E6D5D7724393} + Template + + + + Application + true + NotSet + + + Application + false + true + NotSet + + + + + + + + + + + + + $(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include;$(SalmonEnginePath)include + $(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib;$(SalmonEnginePath)$(Configuration) + + + $(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include;$(SalmonEnginePath)include + $(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib;$(SalmonEnginePath)$(Configuration) + + + + Level3 + Disabled + $(SalmonEnginePath);$(LibsPath)\boost_1_52_0;$(LibsPath)\libogg-1.3.0\include;$(LibsPath)\libvorbis-1.3.2\include;$(LibsPath)\sqplus\sqplus;$(LibsPath)\sqplus\include;$(LibsPath)\DirectXsdk\Include;$(LibsPath)\lpng1510;..\..\jni + TARGET_WIN32;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0501;DEBUG + 4503 + + + true + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;opengl32.lib;glu32.lib;Salmon Engine.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;zlib.lib;libpng15.lib;sqplusD.lib;squirrelD.lib;sqdbglibD.lib;sqstdlibD.lib;dsound.lib;dxguid.lib;%(AdditionalDependencies) + $(LibsPath)\boost_1_52_0\boost_windows\libs_engine\$(Configuration);$(LibsPath)\libogg-1.3.0\win32\VS2010\Win32\$(Configuration);$(LibsPath)\libvorbis-1.3.2\win32\VS2010\Win32\$(Configuration);$(LibsPath)\sqplus\lib;$(LibsPath)\DirectXsdk\Lib\x86;$(LibsPath)\lpng1510\projects\vstudio\Debug Library + + + + + Level3 + MaxSpeed + true + true + $(SalmonEnginePath);$(LibsPath)\boost_1_52_0;$(LibsPath)\libogg-1.3.0\include;$(LibsPath)\libvorbis-1.3.2\include;$(LibsPath)\sqplus\sqplus;$(LibsPath)\sqplus\include;$(LibsPath)\DirectXsdk\Include;$(LibsPath)\lpng1510;..\..\jni + TARGET_WIN32;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0501;NDEBUG + 4503 + + + true + true + true + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;opengl32.lib;glu32.lib;Salmon Engine.lib;libogg_static.lib;libvorbis_static.lib;libvorbisfile_static.lib;zlib.lib;libpng15.lib;sqplus.lib;squirrel.lib;sqdbglib.lib;sqstdlib.lib;dsound.lib;dxguid.lib;%(AdditionalDependencies) + $(LibsPath)\boost_1_52_0\boost_windows\libs_engine\$(Configuration);$(LibsPath)\libogg-1.3.0\win32\VS2010\Win32\$(Configuration);$(LibsPath)\libvorbis-1.3.2\win32\VS2010\Win32\$(Configuration);$(LibsPath)\sqplus\lib;$(LibsPath)\DirectXsdk\Lib\x86;$(LibsPath)\lpng1510\projects\vstudio\Release Library + + + + + + + + + + + + + + \ No newline at end of file diff --git a/windows/Template/main.cpp b/windows/Template/main.cpp new file mode 100644 index 0000000..c60c9b6 --- /dev/null +++ b/windows/Template/main.cpp @@ -0,0 +1,30 @@ +#include "main.h" + +#include "main_code.h" + +int APIENTRY WinMain(HINSTANCE hCurrentInst, HINSTANCE hPreviousInst, + LPSTR lpszCmdLine, int nCmdShow) +{ + + int width = 800; + int height = 480; + + if (CreateEngine(width, height)) + { + + //MyApplication scope + { + TAndroidApplication Application; + + Application.OuterInit(width, height, width, height); + + MainLoop(&Application); + + Application.OuterDeinit(); + } + + DestroyEngine(); + } + + return 0; +} \ No newline at end of file diff --git a/windows/Template/main.h b/windows/Template/main.h new file mode 100644 index 0000000..3b1cd11 --- /dev/null +++ b/windows/Template/main.h @@ -0,0 +1,6 @@ +#pragma once + +/* Path to the engine */ +#include "include/Engine.h" + +#include "main_code.h" \ No newline at end of file