View Single Post
Old 8th March 2019, 13:18   #3
Senior Member
corwwin's Avatar
Join Date: Mar 2002
Location: Kingdom of Amber
Posts: 272
Hi folks

I noticed that, when rotationg a layer, the rotated image is sometimes distorted. In order to avoid this phenomenon, the layer must be bigger than the object you want to rotate, e.g. if your object is 25 x 25 pix, its image must be 35 x 35 with a 5 pix transparent border. In this way, the pixels of the border are not alterated in the rotation. For a better precision, you can also increase the grid size in the rotate init section of the maki script, i.e. object.fx_setGridSize(15,15) instead of object.fx_setGridSize(10,10);

Here is the 2003 frisbeemonkey's volumeknob script I use as basis for object rotation.

// volumeknob.m
// Example of an Volume Knob using rotation
// based on rotation.m found in winamp3/lib
// (Improved, no longer needs HiddenVolume)
// created by FrisbeeMonkey

// 1. Define the following in your XML:
// <layer id="VolumeKnob" image="player.VolumeKnob" x="?" y="?" move="0"/>
// Change the position(x,y) of "VolumeKnob" to the specifics
// of your layer. Make sure the image is facing where you want 0 to be.
// 2. Define your gradient map with your other elements using:
// <bitmap id="" file="player/VolKnobMap.png"/>
// If you need help creating a map file, check:
// 3. Make sure your ticker is called "SongTicker" and is in the same group as
// "VolumeKnob". If you don't have a ticker, add one now.
// 4. Copy this script (and volumeknob.maki) to your scripts folder.
// 5. If you don't have volumeknob.maki, compile this script.
// 6. Add this line to the group that contains your animated layer
// <script id="volumeknob" file="scripts/volumeknob.maki"/>
// 7. Refresh your skin(F5) and try it out.

// never forget to include std.mi
#include "../../../lib/std.mi"

//defines PI as a constant if it hasn't been already
#ifndef PI
#define PI 3.1415926536

//declares volume functions
Function updateVolume(int x, int y);

//declares rotate functions
Function rotateKnob(float newvol);
Function KnobInit();
Function KnobRotateDegree(double r);
Function KnobRotate(double r);

//declares global variables
Global Layer Volume;
Global Map VolumeMap;
Global Timer SongTickerTimer;
Global Text SongTicker;
Global Double KnobR;
Global Boolean VolumeChanging;

//when script is loaded, do this
System.onScriptLoaded() {

// Get the group that has the objects we want
Group pcGroup = getScriptGroup();

// Now that we have the group, get the objects in the group
Volume = pcGroup.findObject("VolumeKnob");
SongTicker = pcGroup.findObject("songticker");

// Initialize our timer
SongTickerTimer = new Timer;

// Load the gradient map
volumeMap = new Map;

//initialize rotation and volume variables and set knob position
VolumeChanging = 0;
float u;
u = System.getVolume();
u = u / 255;

// Clears text area
SongTickerTimer.onTimer() {

// Handles Volume Mouse Events
Volume.onLeftButtonDown(int x, int y) {
VolumeChanging = 1;
updateVolume(x, y);
Volume.onLeftButtonUp(int x, int y) {
if (VolumeChanging) {
VolumeChanging = 0;
updateVolume(x, y);
Volume.onMouseMove(int x, int y) {
if (VolumeChanging) {
updateVolume(x, y);

// Updates Volume Image and System Position
updateVolume(int x, int y) {
int newValue = VolumeMap.getValue(x - Volume.getLeft(), y - Volume.getTop());

// Updates display and SongTicker on Volume changes
System.onVolumeChanged(int newVol) {
Float f = getVolume();
f = f / 255;

int p = (newVol * 100) / 255;
Songticker.setAlternateText("Volume:" + System.integerToString(p) + "%)");

//rotates knob to new orientation
rotateKnob(float newvol){
//finds out how many degrees to rotate
newvol = newvol * 360;
//rotates that many degress, uses negative since we want clockwise rotation

//initializes layer fx settings
KnobInit() {

//converts degrees to radians, then calls KnobRotate
KnobRotateDegree(double r) {
KnobRotate(r * PI / 180.0);

//rotates layer
KnobRotate(double r) {
KnobR = r;
//notifies that a change has been made, therefor update display

//does the actual rotation of the layer
Volume.fx_onGetPixelR(double r, double d, double x, double y) {
return r + KnobR;

System.onScriptUnloading() {
delete SongTickerTimer;
delete VolumeMap;

Have a nice day
corwwin is offline   Reply With Quote