parallax background, accelerometer powered
This is a new script I made with the help of Lukas Morawietz. All the new bind class, and accelerometer events code was made by Lukas (also some suggestions), the position computation, tags and relative is mine.
The script takes the accelerometer values and place the item accordingly. It is size-dependent so the bigger the item is the more it will move. (Items smaller that the screen size will move a bit odd)
The settings are a parameter to control the lerp (smooth change from the previous value to the new one) otherwise it will move a lot. The other is a threshold to avoid small movements if your accelerometer sends changes even when the device rest, for low end devices.
Instructions:
– Choose an item. Remember to set a picture as background and hide the icon and text (or not, that’s up to you)
– Set this script in the resumed event of the item
– Important: detach the item
– Optional but recommended: set the script in the paused event of the item
– Optional: you may want to pin the item too.
The movement is stopped automatically when the launcher lost focus, but I recommend also to set the script in the paused event (specially if you use different desktops). It is made so if you run it from other events (a swipe or even the scripts menu) it stops. Useful if you want to edit the item.
To reload the script just turn off/on the screen. You may want to do it when setting the event and when changing the size of the item.
It works in folders and in panels too. And also you can set it in as much items as you want (with caution) The second video has two items, the galaxy background and the stars, both items has different sizes.
Note: I needed to add a small code to avoid the ‘0-size’ bug. If you get an error when the container is loaded just turn off/on the screen. Also I couldn’t test it myself long enough. If you get an error or it don’t work as expected write a comment.
(Again, thanks Lukas for helping me)
]]>
< ![CDATA[
//Version 1 (version 2 in comments)
var delta=0.04;//between (0,1], to avoid shaking due to accelerometer fast changes ( try low values like 0.1)
var threshold=0;//minimum pixels required to move it, if it shakes when the device rest (try 1,2…)
var accuracy=1; //accuracy of the Sensor. 0 is the fastest but can consume a bit more battery. 3 is battery-friendly, but can be slower. 1 and 2 are a medium value. Default 1
var gyro=LL.getEvent().getItem()||LL.getItemById(LL.getEvent().getData()||-1);
if(gyro==null){
alert(“run this script from an item”);
return;
}
//disable when desired
if(LL.getEvent().getSource()!=”I_RESUMED”&&LL.getEvent().getData()==null)
{
gyro.setTag(“parallax”,null);
return;
}
var cont=gyro.getParent();
//allowed only one
if(gyro.getTag(“parallax”)==”active”)return;
if(gyro.getTag(“parallax”)!=”repeat”){
gyro.setTag(“parallax”,”repeat”);
var name=LL.getCurrentScript().getName();
setTimeout(function(){LL.runScript(name,gyro.getId())},0);
return;
}
gyro.setTag(“parallax”,”active”);
var g=[gyro.getWidth()*gyro.getScaleX()-cont.getWidth(),gyro.getHeight()*gyro.getScaleY()-cont.getHeight()];
xy=[,];
LL.bindClass(“android.hardware.Sensor”);
LL.bindClass(“android.hardware.SensorEventListener”);
LL.bindClass(“android.hardware.SensorManager”);
var sm = LL.getContext().getSystemService(Context.SENSOR_SERVICE);
var orientation = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
var i = {
onAccuracyChanged: function(sensor,accuracy){},
onSensorChanged: function(event) {
if(LL.isPaused()||gyro.getTag(“parallax”)!=”active”){
sm.unregisterListener(l);
gyro.setTag(“parallax”,null);
return;
}
var x=(-event.values[0]+10)/20;
var y=(event.values[1]+10)/20;
if(xy[0]==null)xy=[x,y];
x=(x>1)?1:(x<0)?0:x;
y=(y>1)?1:(y<0)?0:y
//var flags=[true,true];
if(Math.abs(x-xy[0])*delta*g[0]
if(Math.abs(y-xy[1])*delta*g[1]
xy=[xy[0]+(x-xy[0])*delta,xy[1]+(y-xy[1])*delta];
gyro.setPosition(-g[0]*xy[0],-g[1]*xy[1]);
}
};
var l = new SensorEventListener(i);
sm.registerListener(l, orientation,accuracy);
]]>
< ![CDATA[
I set it up and it immediately gave an error on line 9
]]>
< ![CDATA[
Which error?
]]>
< ![CDATA[
Error 9 too….
Can’t find méthod net.pierrox.lightning_launcher.c.a.d.getltemByld(null).(scripthollo#9)
]]>
< ![CDATA[
c.a.k not c.a.d!
]]>
< ![CDATA[
Be sure to run the script from an item.
If you just set it in the resumed and paused events of the item it should work.
If you still have the error tell me
The script has been edited to show a warning instead of an error
]]>
< ![CDATA[
It’s not best manner to import mid-script…
Also how about let Users select accuracy?
]]>
< ![CDATA[
Lukas Morawietz not sure what do you mean with ‘mid-script’
And select accuracy…If that mean something related to the Sensor in the java form I need your help 😛
]]>
< ![CDATA[
Import (or in LL Bind) calls are normally at the beginning of code
]]>
< ![CDATA[
Oh, you mean that. Well, I placed them where they are because this way I don’t call them if the script is not going to run (technically the script runs twice to avoid the 0-size bug) and also when it sets the tag to stop the running one.
I know they normally are at the beginning because they are needed, but not in this case.
Pierre Hébert: does it matter?
]]>
< ![CDATA[
Sensormanager has SENSOR_DELAY_FASTEST, SENSOR_DELAY_GAME and SENSOR_DELAY_NORMAL (listed in descending accuracy and battery consumption)
For me it works with all three but there is a noticeable delay on lower values…
]]>
< ![CDATA[
Lukas Morawietz and even a slower one (to be exact, a intermediate)
Script updated, change the accuracy added. Default is now 1 (sensor game)
]]>
< ![CDATA[
Ok so link this to a widget for example not to the desktop?
]]>
< ![CDATA[
Exactly. The resumed event of an item
]]>
< ![CDATA[
Does this need the Beta or will this work with the latest Stable release?
]]>
< ![CDATA[
Im not getting any errors with this, it just doesnt seem to do anything. What could I be missing?
]]>
< ![CDATA[
Craig L Have you detached the item?
Brian King There is no Beta ATM…
]]>
< ![CDATA[
Craig L Lukas Morawietz detaching the item! I forget to say that sorry.
Description updated with more detailed instructions.
]]>
< ![CDATA[
Fan-bloody-tastic fellas. 10/10
]]>
< ![CDATA[
TrianguloY l detached from grid but still dont notice any movement. Could it be due to landscape orientation or some other desktop setting?
]]>
< ![CDATA[
Craig L Is your item noticeable bigger than your screen?
Has your device an Accelerometer?
Landscape should not be a problem
]]>
< ![CDATA[
I have the same problem. My screen is ten inches and I only use landscape. I shun anything that uses portrait. The widget I used the script on had no affect either and its only taking up about a 3×4 area guesstimating. the only thing I haven’t done so far is place a picture as my background and that’s because I don’t want one.
]]>
< ![CDATA[
Im running a ten inch screen as well. Ive tried with all different sizes and no luck. Elixir 2 shows accelerometer to be functioning properly.
]]>
< ![CDATA[
Ok. Finally got it to work. Had to make it very very large on my tablet before it would start, like 4 times the grid size of the desktop.
]]>
< ![CDATA[
Are you telling me the widget has to literally run off onto other pages of the desktop? No thanks I don’t like scrolling through pages just to see the while item. I don’t like my wallpapers that way and I ain’t going to have my desktop items that way either
]]>
< ![CDATA[
Curtis Sylvester Jr. You don’t have to use it. Watch yourself, your tone isn’t very friendly.
]]>
< ![CDATA[
Tested some more and it doesnt work on a dynamic text item…
]]>
< ![CDATA[
Craig L true! This is an LL bug. I’ll report it.
]]>
< ![CDATA[
Works perfect. 12 from 10 points! Great work TrianguloY Lukas Morawietz
]]>
< ![CDATA[
Curtis Sylvester Jr. If the item is pinned it won’t scroll so you can still have it as a fully wallpaper.
If you don’t have items to scroll, and this makes it scrollable, just disable scrolling.
]]>
< ![CDATA[
This is about the coolest thing I’ve seen via scripting!
]]>
< ![CDATA[
I think I’m going to share it also in the users community.
(But there isn’t a ‘script’ section, and no admins Pierre Hébert)
]]>
< ![CDATA[
Perhaps just a video and direct them here?
]]>
< ![CDATA[
Chris Chastain that’s what I did. I wanted to just share the post so you could see it and I didn’t need to rewrite it, but it seems all of us need to be users of that community.
]]>
< ![CDATA[
Indeed, messages here are private and cannot be seen from elsewhere without being a member of the community.
Anyway the “Share your screen” is the right place: even if scripts are running under the hood, the result is still a great screen 🙂
]]>
< ![CDATA[
Semi-on-topic: would batteryManager and service/listener work similar to this Sensor-mechanism. Or would than need a totally different mechanism to get battery percentage?
]]>
< ![CDATA[
TrianguloY & Lukas Morawietz thank a lot for that amazing script !
Few questions : 1) is it normal that it doesn’t work with widget, or am I doing smth wrong ?
2) I have 2 items in the same panel, set the script on each one, but (it’s normal) they superimpose them. is it possible to have the items at “2 different start point” (not sure that is clear …) and make them move at the same speed (like the script actually do) ? Thanks in advance 🙂
]]>
< ![CDATA[
Just fyi… I’ve been using this with sensor accuracy set to 0 for about a week and haven’t seen any noticeable hit on battery.
]]>
< ![CDATA[
Stahw Down
1) Unfortunately it is. Is the same bug why it don’t work in dynamic texts (already reported).
2) It could be done, but in this case I prefer to suggest alternative ways. If not I’ll think about adding that feature.
So: I guess both items have a background image, and they move at the same velocity, so what about join the images with a image editor and set it in the same item?
How is that layout? How are placed the items? Can you put them in a panel and move the panel?
(As I said, I’ll add the feature if your setup is difficult to do with those tricks 😉
Chris Chastain good to know.
]]>
< ![CDATA[
Chris Chastain fyi ?
Another question : accuracy doesn’t go over 3, right ? I mean if I set it to 9, it won’t move slower ?
]]>
< ![CDATA[
Stahw Down fyi means ‘For Your Information’
Sorry but no, those are android values, 4 and more just don’t exist
]]>
< ![CDATA[
TrianguloY thank you
1) I didn’t notice it was the same bug, sorry
2) it was just to know if I was doing smth wrong. My trick is to set each item in different panel, then include them in the 1st panel. I’ll try your trick too 😉
Thanks again 🙂
]]>
< ![CDATA[
Really nice script (i love your scripts btw :)). It works very well on my galaxy s4 running latest weekly dirty unicorns lollipop build. But somehow i cant figure out how to restart the script… I understand that it stops working from time to time and that turning on and off the screen should restart it. But for me it doesn’t. (the setup seems to be right as it actually works for quite some time, it just doesn’t restart eventually).
– i set the script in the paused and resumed event of a shortcut that zooms to 100p
– i detached the item and pinned it
– the item is considerably bigger than the home screen and the effect was really nice
Do you have any idea? Do I miss anything?
]]>
< ![CDATA[
Strange.
Does it restart if you open/close the recent apps list?
And if you open/close another app?
]]>
< ![CDATA[
no. is there any way to manually restart the script (maybe a shortcut or so)?
]]>
< ![CDATA[
For testing purposes i build another parallax wallpaper (which did not work either if the first item didn’t move). When deleting this item again i got this error message:
Unrecoverable error
At line 79: Wrapped java.lang.NullPointerException:Attempt to invoke virtual method ‘voidandroid.view.View.getHitRect(android.grahics.Rect)’ on a null object reference (Parallax Wallpaper’79)
Maybe this helps you?
]]>
< ![CDATA[
That’s normal.
The script is made so it activates when running from the resumed event of an item, and deactivates when running from another event of that item.
In theory it should work, I’ll try in case recent versions changed something.
( Lukas Morawietz, maybe the listener is not unregister? )
]]>
< ![CDATA[
The tag seems to be used confusingly complex. I have no idea why it’s set to “repeat” at all if it’s reset to “active” right afterwards…
Resetting the “parallax” tag should fix this when it occurs, but it shouldn’t occur at all…
]]>
< ![CDATA[
The listener unregisters itself, this should be a safe action as long as LL doesn’t crash or restart in between.
]]>
< ![CDATA[
I know what the problem is
Tobias Schmidt, when you set the script in the events, where it says ‘pass data to the script…’ do NOT click accept. Click outside of the box to dismiss it (or press the back key)
Pierre Hébert, definitely at least a checkbox is needed in that dialog :/
]]>
< ![CDATA[
Ah the null check again…
]]>
< ![CDATA[
done. thank you ill try it and report back.
two more issues:
1. just for my own understanding: i added a shortcut to a lightning action that does nothing (lock) and made the parallax script run from it. this works but how can it actually run from it as there is nothing to pause or resume?
2. is it my sensor or is there a bug with the script running in landscape mode? – when i run the script in portrait everything works fine, whereas when i run it in landscape mode the picture movement goes the opposite way of what it should: turning my phone left or right makes the picture move up and down – turning it to top or bottom makes the picture move left or right 🙂
my sensor is ok – i checked it.
]]>
< ![CDATA[
Tobias Schmidt every item has own events. check customize -> more -> +
Just set the script there in resumed and paused event.
I guess there is no orientation check at all in there…
]]>
< ![CDATA[
Maybe you need to enable expert mode?
About the orientation…oops, it’s true, there is no check. But the fix is (I hope) really easy, just change the event.values[0]< ->event.values[1]
I’ll post a modified version when I could
]]>
< ![CDATA[
Sorry, i think you get me wrong. I understand how to do it (as i wrote: it works) and I even think I understand the logic behind that. But I don’t understand the logic behind a “resumed” event on the shortcut “lock (do nothing)”. To my understanding a shortcut that does nothing has no events, yet still the script is executed…
And I really have no idea why the picture moves in the wrong direction. My setup: two desktops. One has portrait lock, the other one landscape lock. On the one with portrait lock the picture moves correctly, while in landscape lock it moves wrong.
]]>
< ![CDATA[
like:
var x=(event.values[1]….
var y=(-event.values[0]…. ?
]]>
< ![CDATA[
well….yes! thank you! now the directions are right!
maybe you should consider updating the instructions in the script repository concerning this “null check” and the difference in code when using landscape orientation….
]]>
< ![CDATA[
Nice!
I’ll do it, I hope to have time tonight.
]]>
< ![CDATA[
Nope, I couldn’t.
But I think I made it. Could you test this? (The same instructions as before, but now it should work in both portrait/landscape)
//Version 2
var delta=0.04;//between (0,1], to avoid shaking due to accelerometer fast changes ( try low values like 0.1)
var threshold=0;//minimum pixels required to move it, if it shakes when the device rest (try 1,2…)
var accuracy=1; //accuracy of the Sensor. 0 is the fastest but can consume a bit more battery. 3 is battery-friendly, but can be slower. 1 and 2 are a medium value. Default 1
var tablet = false; //set this to true if your device is a tablet or if the item is moving vertical instead of horizontal and the opposite
var data=LL.getEvent().getData();
if(data==””)data=null;
var gyro=LL.getEvent().getItem()||LL.getItemById(data||-1);
if(gyro==null){
alert(“run this script from an item”);
return;
}
var source=LL.getEvent().getSource();
//disable when desired
if(source!=”I_RESUMED” && data==null)
{
gyro.setTag(“parallax”,null);
return;
}
var cont=gyro.getParent();
//small tweak to avoid strange bugs that happen when the script is run directly
//this only runs itself
if(gyro.getTag(“parallax”)!=”repeat”&&cont.getHeight()==0){
gyro.setTag(“parallax”,”repeat”);
var name=LL.getCurrentScript().getName();
setTimeout(function(){LL.runScript(name,gyro.getId())},0);
return;
}
var token=Math.random();
while(token==gyro.getTag(“parallax”))token=Math.random();
gyro.setTag(“parallax”,token);
var g=[gyro.getWidth()*gyro.getScaleX()-cont.getWidth(),gyro.getHeight()*gyro.getScaleY()-cont.getHeight()];
var portrait=cont.getWidth()
var xy=[,];
LL.bindClass(“android.hardware.Sensor”);
LL.bindClass(“android.hardware.SensorEventListener”);
LL.bindClass(“android.hardware.SensorManager”);
var sm = LL.getContext().getSystemService(Context.SENSOR_SERVICE);
var orientation = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
var i = {
onAccuracyChanged: function(sensor,accuracy){},
onSensorChanged: function(event) {
if(LL.isPaused()){
gyro.setTag(“parallax”,null);
sm.unregisterListener(l);
return;
}
if(gyro.getTag(“parallax”)!=token){
sm.unregisterListener(l);
return;
}
if(portrait!=(cont.getWidth()
sm.unregisterListener(l);
cont.setTag(“parallax”,null);
var name=LL.getCurrentScript().getName();
setTimeout(function(){LL.runScript(name,gyro.getId())},0);
return;
}
if(portrait!=tablet){
var v=[-event.values[0],event.values[1]];
}else{
var v=[event.values[1],event.values[0]];
}
var x=(v[0]+10)/20;
var y=(v[1]+10)/20;
if(xy[0]==null)xy=[x,y];
x=(x>1)?1:(x<0)?0:x;
y=(y>1)?1:(y<0)?0:y
//var flags=[true,true];
if(Math.abs(x-xy[0])*delta*g[0]
if(Math.abs(y-xy[1])*delta*g[1]
xy=[xy[0]+(x-xy[0])*delta,xy[1]+(y-xy[1])*delta];
gyro.setPosition(-g[0]*xy[0],-g[1]*xy[1]);
}
};
var l = new SensorEventListener(i);
sm.registerListener(l, orientation,accuracy);
]]>
< ![CDATA[
Tested. works in both portrait & landscape mode.
]]>
< ![CDATA[
Hey TrianhuloY, this script looks awesome but I cant seem to get it to work. I may well be doing something very silly but I’m buggered as to where I’m going wrong.
I don’t receive any errors, it just doesn’t actually do anything for me until I lock/unlock my phone (or navigate away from the desktop in one way or another). When I do lock/unlock it immediately changes where on the desktop it is sitting, based (as near as I can tell) on the way my phone had been moving about while the screen was last active, and wwhile it was locked.
Sorry if that makes no sense, I’m still very new to this whole thing.
]]>
< ![CDATA[
Try to change the delta value to something bigger, 0.5 or so. When it reacts, make it lower to avoid shaking until you think it’s ok.
If it still doesn’t work try with 1 or even 10.
If still doesn’t work, tell me.
(Also, make sure you are using the second version in the comments)
]]>
< ![CDATA[
Just gave it a shot and still not getting anything, it’s as though the script is running but it just doesn’t actually update until I navigate TO the desktop.
Just to make sure, do I need to sset anything in the binding? Also I got the script straight from the repository, titled New Script. A cursory look over the script in the comments compared to the one I’m using certainly looks the same.
]]>
< ![CDATA[
Binding? This script is not for the binding.
I checked with the online version, and it works fine.
Just to make sure:
1) did you set the script to run in the resumed event of the item?
2) did you tried to change the number I told you?
3) does your device have accelerometer?
If not, what if you change the accuracy to 0? And 3?
]]>
< ![CDATA[
Hey Triangulo, sorry for such a late reply.
Turns out I was doing something silly, the script works once you resize the item to be larger than a page on your desktop. I, like a silly bugger, had kept it at about half a page while I was setting it up. Very silly mistake, but all fixed now. Thanks for your help and once again thanks to you and everyone who helped in writing the amazing script
]]>