2017-11-16

VT villains dance

Yesterday afternoon, over at VT, Purple was the DJ for a dance that celebrated villains of all sorts. Mistress and I thought this was a perfect chance to do one of our "hers and hers" outfit combinations...


















A full album of all the photos I took can be found over on Google Photos.

2017-11-09

VT metal dance

Yesterday afternoon Purple was the DJ at VT for a metal-themed dance. Not so much meal the music (although there was a bit of that), more metal the material. Mistress and I used it as a good reason to get all shiny.

















A full album of all the photos I took at the event can be found over on Google Photos.

2017-11-06

Flexible linkset

Yesterday afternoon Mistress had reason to play around with flexible path values for a linkset. In doing so she mentioned that it was a bit of a pain to have to set the parameters individually for each item in the linkset. Never having really played with this before, I was a little surprised to find that it's a prim parameter that you can't set on more than one prim at once; especially given it's one you can set on more than one prim at once from a script.

So, for fun, I knocked up a little tool that would let her experiment quickly and easily. Z&A Flex Linkset was born:

//////////////////////////////////////////////////////////////////////
// Z&A Flex Linkset
// By Antony Fairport
//
// Z&A Flex Linkset - Apply flexible path params to a whole linkset.
//
// Revision history:
// ------------------------------------------------------------
//
// 2017-11-05
// Initial revision.
//////////////////////////////////////////////////////////////////////
// Globals.
integer g_iSoftness = 2;
float g_nGravity = 0.300;
float g_nFriction = 2.000;
float g_nWind = 0.000;
float g_nTension = 1.000;
vector g_vForce;
//////////////////////////////////////////////////////////////////////
// Refresh the flexible path for the whole linkset.
RefreshFlexi()
{
llSetLinkPrimitiveParamsFast( LINK_SET, [
PRIM_FLEXIBLE, TRUE, g_iSoftness, g_nGravity, g_nFriction, g_nWind, g_nTension, g_vForce
] );
}
//////////////////////////////////////////////////////////////////////
// Get a parameter, with error checking and reporting.
float GetParam( list lCmd, string sName, float nCurrent, float nMin, float nMax )
{
float n = (float) llList2String( lCmd, 2 );
if ( ( n >= nMin ) && ( n <= nMax ) )
{
nCurrent = n;
}
else
{
llSay( 0, "Invalid value. " + sName + " should be in the range " +
( (string) nMin ) + " to " + ( (string) nMax ) + " inclusive." );
}
return nCurrent;
}
//////////////////////////////////////////////////////////////////////
// Default state.
default
{
//////////////////////////////////////////////////////////////////
// State entry.
state_entry()
{
// Set the initial state.
RefreshFlexi();
// Start listening to the owner.
llListen( 0, "", llGetOwner(), "" );
}
//////////////////////////////////////////////////////////////////
// Handle a listen.
listen( integer channel, string name, key id, string message )
{
if ( ( channel == 0 ) && ( id == llGetOwner() ) )
{
// Break up what was said.
list lCmd = llParseString2List( message, [ " " ], [] );
string sPrefix = llList2String( lCmd, 0 );
// Is it a flex command?
if ( sPrefix == "flex" )
{
// It is. Pull out the next part.
string sCmd = llList2String( lCmd, 1 );
if ( sCmd == "soft" )
{
integer i = (integer) llList2String( lCmd, 2 );
// Does it look like a valid softness value?
if ( ( i >= 0 ) && ( i <= 3 ) )
{
g_iSoftness = i;
}
else
{
llSay( 0, "Invalid value. Softness should be in the range 0 to 3 inclusive." );
}
}
else if ( sCmd == "grav" )
{
g_nGravity = GetParam( lCmd, "Gravity", g_nGravity, -10.0, 10.0 );
}
else if ( sCmd == "drag" )
{
g_nFriction = GetParam( lCmd, "Drag", g_nFriction, 0.0, 10.0 );
}
else if ( sCmd == "wind" )
{
g_nWind = GetParam( lCmd, "Wind", g_nWind, 0.0, 10.0 );
}
else if ( sCmd == "ten" )
{
g_nTension = GetParam( lCmd, "Tension", g_nTension, 0.0, 10.0 );
}
else if ( sCmd == "fx" )
{
g_vForce.x = GetParam( lCmd, "Force (X)", g_vForce.x, -10.0, 10.0 );
}
else if ( sCmd == "fy" )
{
g_vForce.y = GetParam( lCmd, "Force (Y)", g_vForce.y, -10.0, 10.0 );
}
else if ( sCmd == "fz" )
{
g_vForce.z = GetParam( lCmd, "Force (Z)", g_vForce.z, -10.0, 10.0 );
}
else if ( sCmd == "show" )
{
llSay( 0, "Current flexible path parameters:\n" +
"Softness: " + ( (string) g_iSoftness ) + "\n" +
"Gravity.: " + ( (string) g_nGravity ) + "\n" +
"Drag....: " + ( (string) g_nFriction ) + "\n" +
"Wind....: " + ( (string) g_nWind ) + "\n" +
"Force X.: " + ( (string) g_vForce.x ) + "\n" +
"Force Y.: " + ( (string) g_vForce.y ) + "\n" +
"Force Z.: " + ( (string) g_vForce.z ) + "\n" );
}
else if ( sCmd == "reset" )
{
llResetScript();
}
else if ( sCmd == "done" )
{
llSay( 0, "Sorry you don't want me any more. Enjoy your flexibility. :-(" );
llRemoveInventory( llGetScriptName() );
}
else if ( sCmd == "help" )
{
llSay( 0, "flex < soft | grav | drag | wind | ten | fx | fy | fz > <value>" );
llSay( 0, "flex show" );
llSay( 0, "flex reset" );
llSay( 0, "flex done" );
}
// Finally, refresh.
RefreshFlexi();
}
}
}
}
The script is designed so that it listens to the object owner in local chat, and accepts commands for setting the different parameters. When a parameter is given it's applied to the whole linkset. Commands include:

flex soft <value>
flex grav <value>
flex drag <value>
flex wind <value>
flex ten <value>
flex fx <value>
flex fy <value>
flex fz <value>

As well as commands for setting the flexible path parameters, there are also commands for controlling the script itself. To see the current parameters:

flex show

To reset the parameters to their default:

flex reset

And when you're done with the script and you want it to remove itself from the object:

flex done

And that's it. It was fun to knock together, Mistress had fun playing around with it, hopefully it's of some use to someone else too.

2017-11-04

VT stars and sparkles dance

Yesterday afternoon VT started a new week of dances, this time with a theme of "stars and sparkles". Mistress was so happy that it was finally the reason to get out a catsuit she's being wanting to wear in public (and in the right lighting) for ages. Me.... well, the problem is, when Mistress knows what her outfit is and when there's time to spare, she does like to create. I ended up wearing such a creation...














A full album of all the photos I took at the dance can be found over on Google Photos.

2017-11-02

VT day of the dead dance

Yesterday afternoon Miss Eve was standing in for Purple as the Wednesday DJ, with a "day of the dead" theme. Mistress dressed up in an amazing costume and I.... well, I threw on some latex and roses and called it finished...














A full album of photos from the dance can be found over on Google Photos.