Plymouth theming guide (part 3)
Now the basics have been covered in part 2 of this guide, we can now tackle some more advanced tasks. This part is for beginners to intermediate. If you have never programmed, then this will be a rough introduction to the field and thus you may need to ask for help about some confusing aspects.
Until now, all the examples have been simple assignments and there hasn’t been much “programming”. At the end of the last part, the background image needed to be scaled without distorting the aspect ratio. If the image is wider than the screen, then the image needs to be scaled up to the height of the screen and let the sides hang over the edges. If the image is taller than the screen, the image should be scaled to the screen width and allow the top and bottom to go beyond the edge of the screen.
You can get the screen ratio using the Window.GetWidth and Window.GetHeight functions introduced in the previous part. The ratio is height to width. The greater the number, the taller the proportions.
screen_ratio = Window.GetHeight() / Window.GetWidth();
GetWidth and GetHeight functions also work on images.
flower_image_ratio = flower_image.GetHeight() / flower_image.GetWidth();
To create the scaled image, the scale factor needs to be determined. If the screen is tall, we make the scale factor such that the image will be the same hight as the screen, and allow it to dangle off the edges. For a wide screen, make the image match the width and allow the top and bottom to go beyond the edges. The scale factor can then be used to scale the image width and height.
if (screen_ratio > flower_image_ratio) { # Screen ratio is taller than image ratio, we will match the screen height scale_factor = Window.GetHeight() / flower_image.GetHeight(); } else { # Screen ratio is wider than image ratio, we will match the screen width scale_factor = Window.GetWidth() / flower_image.GetWidth(); } scaled_flower_image = flower_image.Scale(flower_image.GetWidth() * scale_factor, flower_image.GetHeight() * scale_factor); flower_sprite = Sprite(scaled_flower_image); # Create the a sprite using the scaled image
Now the image is scaled to the correct width and height, it needs to be placed in the centre of the screen.
flower_sprite.SetX(Window.GetWidth() / 2 - scaled_flower_image.GetWidth() / 2); # Place in the centre flower_sprite.SetY(Window.GetHeight() / 2 - scaled_flower_image.GetHeight() / 2); flower_sprite.SetZ(-10000); # Place right at the back
If everything went right, your code should look like this:
flower_image = Image("flower.png"); screen_ratio = Window.GetHeight() / Window.GetWidth(); flower_image_ratio = flower_image.GetHeight() / flower_image.GetWidth(); if (screen_ratio > flower_image_ratio) { # Screen ratio is taller than image ratio, we will match the screen height scale_factor = Window.GetHeight() / flower_image.GetHeight(); } else { # Screen ratio is wider than image ratio, we will match the screen width scale_factor = Window.GetWidth() / flower_image.GetWidth(); } scaled_flower_image = flower_image.Scale(flower_image.GetWidth() * scale_factor, flower_image.GetHeight() * scale_factor); flower_sprite = Sprite(scaled_flower_image); # Create the a sprite using the scaled image flower_sprite.SetX(Window.GetWidth() / 2 - scaled_flower_image.GetWidth () / 2); # Place in the centre flower_sprite.SetY(Window.GetHeight() / 2 - scaled_flower_image.GetHeight() / 2); flower_sprite.SetZ(-10000); # Place right at the back
If you wish for your background to match the one in your desktop, copy it to the theme directory and edit the script to load the image of that filename. Only PNG files are allowed.
Finally to install your theme into the ramdisk, so it is loaded when your computer starts, add –rebuild-initrd to the plymouth-set-default-theme command. Do be careful not to install a theme which deadlocks. Make sure you have a backup kernel or initrd image if all goes wrong
plymouth-set-default-theme mytheme --rebuild-initrd
Animation
Start by making a new sprite with an image of a butterfly:
butterfly_image = Image("butterfly0.png"); butterfly_sprite = Sprite(butterfly_image);
At the bottom of the block of code you are editing, there is a function named refresh_callback. This is called 50 times a second (unless the system is busy) just before refreshing the screen. Within the function, you can move the sprites around and these movements will be updated on the screen. Take a look at this example:
progress = 0; fun refresh_callback () Â { Â Â Â progress++; butterfly_sprite.SetX(progress); Â }
At every refresh, the butterfly will be moved one pixel to the right. To make the butterfly flap it’s wings, several frames are needed. Instead just loading one image, this requires an array of images to be loaded. Replace the original two lines that loaded the butterfly image and created the sprite, with these:
for (i = 0; i < 4; i++) butterfly_images[i] = Image("butterfly" + i + ".png"); butterfly_sprite = Sprite();
You can append strings to numbers to create the four filenames. Secondly, if a sprite has not been attached to an image, it will simply be empty until one is set. Adding the following line into therefresh_callback function should rotate through the 4 butterfly frames. Because the progress is divided by 6 in order to slow the animation to one frame every 6 refreshes, we use a Math library function to round down a number to an integer.
butterfly_sprite.SetImage(butterfly_images[Math.Int(progress / 6) % 4]);
There are some other math functions available, sin and cos are often useful. Replace the SetX line with the following to make the butterfly go around in a circle around the centre of the screen.
theta = progress / 100; butterfly_sprite.SetX(Window.GetWidth() / 2 + Math.Sin(theta) * 200); butterfly_sprite.SetY(Window.GetHeight() / 2 - Math.Cos(theta) * 200);
Now the butterfly looks a little weird pointing the wrong way as it is going around in a circle. We need to rotate the butterfly image so it is flying forward. Add .Rotate(theta) to the image while setting it to the sprite. This creates a new image which is rotated by the angle theta.
butterfly_sprite.SetImage(butterfly_images[Math.Int(progress / 5) % 4].Rotate(theta));
If you have reached this point, you should now have all the knowledge you need to start creating your own themes. For a full list of available functions and script syntax take a look at the freedesktop plymouth script wiki. Good luck, have fun and make some nice splash screens.
Thanks for this guide – it’s been extremely helpful! :)
I am experiencing one problem that my google searches have failed me on that I’m hoping someone might be able to answer..
No matter what theme I set using plymouth-set-default-theme mytheme –rebuild-initrd, I always see Fedora 12’s default “charge” theme. However, I do see the theme I attempt to set during shutdown (just not on boot).
Any suggestions?
Thanks,
Mark
Please disregard my question above. A much needed ‘yum update’ fixed the issue. (Doh!) :D
Hello, thank you for writing this excellent theming guide! It’s been a fun learning process.
The butterfly sprite appeared and moved after entering the first two code blocks of the animation section, but it seems the third code block of the animation section prevents the butterfly sprites from appearing alltogether.
I believe I followed the instructions correctly and replaced the first block with the third.
Can you help me? I’ve been trying to find a workaround for hours.
nevermind my last comment, I had to put in the codeblocks that followed, lol. Now it works!
Any idea how to do a “rebuild-initramfs”? The plymouth theme binary seems to only offer initrd.
Maybe something obvious to kernel people, but I can’ seem to figure it out.
Thanks!
Rebuilding a initramfs can be tricky, make sure you first make a backup of your current initramfs and test the copy with a reboot before messing with it. If you break it, you prolly need to reinstall or know your way around rescue images to fix it.
Making a new one depends on your distro. Best way to find out how is to google on ” rebuild initramfs”.
As root you should be able to rebuild one with the following command on recent ubuntu or debian: update-initramfs -u
Hmm, was a bit to quick with the reply :)
plymouth-set-default-theme -R [your theme]
that should do the trick
Thanks for the info, daftwullie. I ended up inspecting the latest plymouth package at koji.fedoraproject.org, and saw that the way it’s done in fedora is:
/sbin/new-kernel-pkg –package kernel –mkinitrd –dracut –depmod –install $(uname -r)
That updates initramfs, which fedora uses by default (instead of initrd). After doing that though, I think Fedora’s default initramfs doesn’t require doing that, just doing the plymouth-set-default-theme as you suggested.
Nevertheless, I’m running nvidia proprietary drivers, so the kernel mode-setting on boot is flakey. It worked awhile ago for 1280×1024 but now doesn’t work at all! I just get the text plymouth screen.
Also, I’d like to thank the owner of this page for the tutorial. I referenced it quite a bit when I was building my “Seven” theme.
http://kde-look.org/content/show.php/Seven+Plymouth+Theme?content=128652
Any one help me to do the theming in ubuntu.
I’ve made the theme and replaced theimages of sabily theme with my on images.But at boot time ,old sabily theme appears .What should i do?
Hello, your Themes are great. But Ive got a Question, Im trying to style up your Dandelion Screen. But Actually It looks like this, the Leaves are not soo good :(
http://www.youtube.com/watch?v=j0NGx5C1iGs
And is it possible to show another progress_bar when shutdowning?
Thanks in Advance, Ive uploaded my Files up here :)
http://ubuntuone.com/p/jgk/
Hi, I followed all the guide and looked at source code but can’t find the answer for my issue.
I’m running Debian Squeeze (for that matters) and the “progress” value returned by Plymouth doesn’t match boot progress at all. At the end of boot value is about 0.2.
Today I’m using a ratio based on duration (by Plymouth) and a manually assigned boot time variable, which is not really great …
Anyone for my issue ? thanks.
How can I do my own progress bar? with my own pictures… can you show me some eg? thanks, my email is: elementalwattson@gmail.com
By the way, your tutorial is perfect… but I am new on programming and scripting… I made my own theme with animations by following your guide. The progress bar animation is far to known to me… I’ll appreciate if you send me an explicative way to do that… Thanks again and nice guide, dude. :)
Hi, great guide, thank you. I wanted to know how to determine Width/Height if you have two monitors, is it possible to adjust plymouth screen for each monitor correctly ?