home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
VSCPPv8.zip
/
VACPP
/
IBMCPP
/
samples
/
IOC
/
HELLO6
/
AEARTHW6.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1995-04-07
|
45KB
|
589 lines
/*****************************************************************************
* HELLO WORLD SAMPLE PROGRAM - Version 6: Class Implementation (aearthw6.cpp)*
* *
* COPYRIGHT: Copyright (C) International Business Machines Corp., 1992,1995. *
* *
* DISCLAIMER OF WARRANTIES: *
* The following [enclosed] code is sample code created by IBM *
* Corporation. This sample code is not part of any standard IBM product *
* and is provided to you solely for the purpose of assisting you in the *
* development of your applications. The code is provided "AS IS", *
* without warranty of any kind. IBM shall not be liable for any damages *
* arising out of your use of the sample code, even if they have been *
* advised of the possibility of such damages. *
*****************************************************************************/
// NOTE: WE RECOMMEND USING A FIXED-SPACE FONT TO LOOK AT THE SOURCE.
#ifndef _IBASE_ //Make sure ibase.hpp is included
#include <ibase.hpp> // since that is where IC_<environ>
#endif // is defined.
#ifdef IC_PM //For PM, V5
#define INCL_GPIPRIMITIVES // include the V5
#define INCL_GPIPATHS // drawing routines V5
#include <os2.h> // from the OS/2 libraries V5
#endif //V5
#ifdef IC_MOTIF //For MOTIF, V5
extern "C" { // include the X-Windows V5
#include <X11/Xlib.h> // libraries for drawing and V5
#include <X11/Intrinsic.h> // XtDisplay and XtWindow intrinsics V5
} //V5
#endif //V5
#include <stdlib.h> //Include rand function for twinkle V6
#include "aearthw6.hpp" //v6
/************************************************************************** V5
* AEarthWindow :: AEarthWindow - Constructor for the Earth window * V5
**************************************************************************/ //V5
AEarthWindow :: AEarthWindow(unsigned long windowId, //V5
IWindow * parowWindow, //V5
const IRectangle& rect) //V5
:IStaticText(windowId, parowWindow, parowWindow, rect) //V5
,atmosphereLayers(3) //V5
,spaceColor(IColor::black) //V5
,globeColor(IColor::cyan) //V5
,starColor(IColor::white) //V5
,starIntensity(bright) //V6
,twinkling(false) //V6
{ //V5
/*-------------------- Construct Paint Handler and Show ------------------| V5
| The paintHandler is attached to the AEarthWindow object to begin | V5
| handling paint events. Each time the static text window needs to | V5
| be repainted, the APaintHandler::paintWindow function will be | V5
| called. The first repaint occurs because of IWindow::show. | V5
|------------------------------------------------------------------------*/ //V5
paintHandler.handleEventsFor(this); //V5
show(); //V5
} /* end AEarthWindow :: AEarthWindow(...) */ //V5
/************************************************************************** V5
* AEarthWindow :: ~AEarthWindow - Destructor for Earth window * V5
**************************************************************************/ //V5
AEarthWindow :: ~AEarthWindow() //V5
{ //V5
/*-------------------- Stop and Delete Paint Handler ---------------------| V5
| Tell paintHandler to stop handling events for AEarthWindow. | V5
|------------------------------------------------------------------------*/ //V5
paintHandler.stopHandlingEventsFor(this); //V5
} /* end AEarthWindow :: ~AEarthWindow() */ //V5
/************************************************************************** V5
* APaintHandler :: paintWindow * V5
* This function calls the paintWorld function for the * V5
* AEarthWindow object which repaints the entire static text window. * V5
* The IParameter2 parameter of the IPaintEvent is always passed to * V5
* paintWorld, but it is only used for the AIX implementation. * V5
**************************************************************************/ //V5
IBase::Boolean //V5
APaintHandler :: paintWindow(IPaintEvent & paintEvent) //V5
{ //V5
/*------------------ Call AEarthWindow Paint World Function --------------| V5
| Get a pointer the AEarthWindow object from the paint event and use it | V5
| to call the paintWorld function. | V5
|------------------------------------------------------------------------*/ //V5
return ( ((AEarthWindow *)paintEvent.window())->paintWorld()); //V5
} /* end APaintHandler :: paintWindow(...) */ //V5
/************************************************************************** V5
* AEarthWindow :: paintWorld - paint a view of Earth from space * v5
* This function provides an example of how to use underlying low-level * V5
* calls in conjuction with the User Interface Class Library. In this * V5
* case, native graphics routines are used to draw a view of Earth from * V5
* space in an IStaticText control. * V5
**************************************************************************/ //V5
IBase::Boolean //V5
AEarthWindow :: paintWorld() //V5
{ //V5
Boolean worldPainted = false;
/*----------------------- Construct Color Objects ------------------------| V5
| Construct an IColor object for each color used in the graphical window. | V5
|------------------------------------------------------------------------*/ //V5
const IColor //V5
arcColor[4] = //V5
{globeColor, IColor::blue, IColor::darkCyan, IColor::darkBlue}; //V5
/*------------------- Get Presentation Space Objects ---------------------| V5
| Get the presentation space handle (called "graphics context" in AIX) | V5
| and the rectangle of the area that needs to be painted. | V5
|------------------------------------------------------------------------*/ //V5
const IPresSpaceHandle //V5
hps(presSpace()); //V5
const IRectangle //V5
psRect(rect()); //V5
/*------------------- Construct Squares for Arc Casings ------------------| V5
| Construct four squares such that the leftCenter, topCenter, and | v5
| rightCenter points describe the arcs to be drawn for the Earth and | V5
| its atmosphere. The squares are constructed from IRectangle objects | V5
| positioned initially at the center of the presentation space | V5
| rectangle and then moved 1/2 the square's width to the left and a | V5
| full square's height plus an arbitrary offset down. | v5
|------------------------------------------------------------------------*/ //V5
const int arcs=4; //V5
const float //V5
arcDropFactor[arcs] = {1.0/8, 1.0/16, 1.0/32, 0}, //V5
arcSizeFactor[arcs] = {9.0/4, 21.0/8, 45.0/16, 3}; //V5
const long //V5
psHeight=psRect.height(); //V5
long //V5
arcDrop, //V5
arcDiameter; //V5
IPair //V5
arcOffset; //V5
IRectangle //V5
arcSquare[arcs]; //V5
int i; //V5
for (i=0;i<arcs;i++ ) //V5
{ //V5
arcDrop = psHeight*arcDropFactor[i]; //V5
arcDiameter = psHeight*arcSizeFactor[i]; //V5
arcOffset = IPair(-1*arcDiameter/2,-1*arcDiameter-arcDrop); //V5
arcSquare[i] = IRectangle(psRect.center(), //V5
ISize(arcDiameter, arcDiameter)); //V5
arcSquare[i].moveBy(arcOffset); //V5
} //V5
#ifdef IC_MOTIF //V5
/************************************************************************** V5
***** MOTIF-specific code - BEGIN ***** V5
**************************************************************************/ //V5
/*----------------- Construct X-lib Draw Function Arguments --------------| V5
| Construct the window and display objects needed by the X-lib drawing | V5
| functions from the window handle, which is the widget ID. | V5
| XtWindow and XtDisplay are X-lib intrinsic functions. | V5
|------------------------------------------------------------------------*/ //V5
const Window //V5
xWindow(XtWindow(handle())); //V5
Display //V5
*xDisplay(XtDisplay(handle())); //V5
/*------------------------------- Color Space ----------------------------| V5
| Set the background color to space, which is IColor::black. | V5
| Note that because the X-Windows origin is at the top of the | V5
| window as opposed to the bottom in PM, the X-Windows rectangle | V5
| top must be computed by subtracting the arc rectangle's top | V5
| coordinate from the presentation space rectangle's height. | V5
|------------------------------------------------------------------------*/ //V5
XSetForeground(xDisplay, hps, spaceColor.asPixel()); //V5
XFillRectangle(xDisplay, xWindow, hps, //V5
psRect.left(), //V5
psRect.height()-psRect.top(), //V5
psRect.width(), //V5
psRect.height()); //V5
/*-------------------- Draw the Earth and Atmosphere ---------------------| V5
| Draw the earth and the number of layers of atmosphere specified in | V5
| atmosphereLayers. arcSquare[0] contains the arc dimension for the | V5
| earth and the other arcSquare objects specify each atmosphere layer. | V5
| Each arc is drawn by calling the Xlib functions for setting the | V5
| foreground color and for drawing an arc and filling it with the | V5
| foreground color. The arc is described using rectangle coordinates. | V5
| Note that because the X-Windows origin is at the top of the | V5
| window as opposed to the bottom in PM, the X-Windows rectangle | V5
| top must be computed by subtracting the arc rectangle's top | V5
| coordinate from the presentation space rectangle's height. | V5
|------------------------------------------------------------------------*/ //V5
for(i=atmosphereLayers;i>=0;i--) //V5
{ //V5
XSetForeground(xDisplay, hps, arcColor[i].asPixel()); //V5
XFillArc(xDisplay, xWindow, hps, //V5
arcSquare[i].left(), //V5
psHeight-arcSquare[i].top(), //V5
arcSquare[i].width(), //V5
arcSquare[i].height(), //V5
0,180*64 ); //V5
} //V5
/************************************************************************** V5
***** MOTIF-specific code - END ***** V5
**************************************************************************/ //V5
#endif //V5
#ifdef IC_PM //V5
/************************************************************************** V5
***** PM-specific code - BEGIN ***** V5
**************************************************************************/ //V5
/*------------------------------- Color Space ----------------------------| V5
| Set the background color to space, which is IColor::black. | V5
|------------------------------------------------------------------------*/ //V5
POINTL //V5
origin=IPoint(0,0).asPOINTL(), //V5
maxPoint=((IPoint)psRect.size()).asPOINTL(); //V5
//V5
GpiMove (hps, &origin); //V5
GpiSetColor (hps, spaceColor.index()) ; //V5
GpiBox (hps, DRO_OUTLINEFILL, &maxPoint, 0, 0) ; //V5
/*-------------------- Draw the Earth and Atmosphere ---------------------| V5
| Draw the earth and the number of layers of atmosphere specified in | V5
| atmosphereLayers. arcSquare[0] contains the arc dimension for the | V5
| earth and the other arcSquare objects specify each atmosphere layer. | V5
| Each arc is drawn by calling the PM Gpi functions for setting the | V5
| foreground color and for drawing an arc and filling it with the | V5
| foreground color. The arc is described using rectangle coordinates. | V5
|------------------------------------------------------------------------*/ //V5
POINTL //V5
ptlist[3]; //V5
for(i=atmosphereLayers;i>=0;i--) //V5
{ //V5
ptlist[0]=arcSquare[i].leftCenter().asPOINTL(); //V5
ptlist[1]=arcSquare[i].topCenter().asPOINTL(); //V5
ptlist[2]=arcSquare[i].rightCenter().asPOINTL(); //V5
GpiSetColor(hps, arcColor[i].index()); //V5
GpiBeginPath(hps, 1L); //V5
GpiMove(hps,&ptlist[0]); //V5
GpiPointArc(hps,&ptlist[1]); //V5
GpiLine(hps,&ptlist[0]); //V5
GpiEndPath(hps); //V5
GpiFillPath(hps,1L,FPATH_ALTERNATE); //V5
} //V5
/************************************************************************** V5
***** PM-specific code - END ***** V5
**************************************************************************/ //V5
#endif //V5
/*--------------------------- Paint the Stars ----------------------------| V5
| Call the AEarthWindow function for painting the stars. | V5
|------------------------------------------------------------------------*/ //V5
worldPainted=paintStars(); //V5
return (worldPainted); //V5
} /* end AEarthWindow :: paintWorld(..) */ //V5
/************************************************************************** V5
* AEarthWindow :: paintStars - paint the stars in the Earth window * v5
* This function extends the example of how to use underlying low-level * V5
* calls in conjuction with the User Interface Class Library. In this * V5
* case, native graphics routines are used to draw points which appear * V5
* as stars in space. * V5
**************************************************************************/ //V5
IBase::Boolean //V5
AEarthWindow :: paintStars() //V5
{ //V5
Boolean starsPainted = false; //V5
/*------------------- Get Presentation Space Objects ---------------------| V5
| Get the presentation space handle (called "graphics context" in AIX) | V5
| and the rectangle of the area that needs to be painted. | V5
|------------------------------------------------------------------------*/ //V5
const IPresSpaceHandle //V5
hps(presSpace()); //V5
const IRectangle //V5
psRect(rect()); //V5
/*------------------- Construct Stars from IPoints -----------------------| V5
| Construct a star array where each star is a point within the | V5
| presentation space rectangle. Each point is computed as a fraction | V5
| of the psRect size offset from the origin of the psRect. The | V5
| starIntensity will indicate if the star is made up of one point(dim), | V5
| made up of five points(bright), or randomly dim or bright(twinkle). | V5
|------------------------------------------------------------------------*/ //V5
const int //V5
stars=13; //V5
const IPair //V5
psOrigin(psRect.bottomLeft()), //V5
psSize(psRect.size()); //V5
Intensity //V6
currentIntensity; //V6
int //V5
i, j; //v6
if (twinkling) currentIntensity = twinkle; //V6
else currentIntensity = starIntensity; //V6
AStar //v6
star[stars]; //v6
star[0] =AStar(psOrigin+psSize.scaledBy(0.98,0.43),currentIntensity); //v6
star[1] =AStar(psOrigin+psSize.scaledBy(0.70,0.69),currentIntensity); //v6
star[2] =AStar(psOrigin+psSize.scaledBy(0.20,0.50),currentIntensity); //v6
star[3] =AStar(psOrigin+psSize.scaledBy(0.80,0.63),currentIntensity); //v6
star[4] =AStar(psOrigin+psSize.scaledBy(0.05,0.41),currentIntensity); //v6
star[5] =AStar(psOrigin+psSize.scaledBy(0.50,0.69),currentIntensity); //v6
star[6] =AStar(psOrigin+psSize.scaledBy(0.60,0.94),currentIntensity); //v6
star[7] =AStar(psOrigin+psSize.scaledBy(0.10,0.87),currentIntensity); //v6
star[8] =AStar(psOrigin+psSize.scaledBy(0.40,0.81),currentIntensity); //v6
star[9] =AStar(psOrigin+psSize.scaledBy(0.25,0.69),currentIntensity); //v6
star[10]=AStar(psOrigin+psSize.scaledBy(0.75,0.63),currentIntensity); //v6
star[11]=AStar(psOrigin+psSize.scaledBy(0.30,0.87),currentIntensity); //v6
star[12]=AStar(psOrigin+psSize.scaledBy(0.95,0.87),currentIntensity); //v6
#ifdef IC_MOTIF //V5
/************************************************************************** V5
***** MOTIF-specific code - BEGIN ***** V5
**************************************************************************/ //V5
/*----------------- Construct X-lib Draw Function Arguments --------------| V5
| Construct the window and display objects needed by the X-lib drawing | V5
| functions from the window handle, which is the widget ID. | V5
| XtWindow and XtDisplay are X-lib intrinsic functions. | V5
|------------------------------------------------------------------------*/ //V5
const Window //V5
xWindow(XtWindow(handle())); //V5
Display //V5
*xDisplay(XtDisplay(handle())); //V5
/*--------------------------- Draw the Stars -----------------------------| V5
| Set the foreground color to white, and then draw each star by calling | V5
| the Xlib function for drawing a point. The thirteen stars are each | V5
| described as coordinates within the presentation space. | V5
| Note that because the X-Windows origin is at the top of the | V5
| window as opposed to the bottom in PM, the y coordinate of the | V5
| X-Windows point must be computed by subtracting the star's y | V5
| coordinate from the presentation space rectangle's height. | V5
|------------------------------------------------------------------------*/ //V5
const long //V5
psHeight=psRect.height(); //V5
IPoint //V6
starPoint; //V6
for (i=0;i<stars;i++) //V5
{ //V5
XSetForeground(xDisplay, hps, starColor.asPixel()); //V5
for(j=0;j<5;j++) //V6
{ //V6
starPoint=star[i].point(j); //V6
if (j==1 && star[i].intensity()==dim) //V6
XSetForeground(xDisplay, hps, spaceColor.asPixel()); //V6
XDrawPoint(xDisplay, xWindow, hps, //V5
starPoint.x(), psHeight-starPoint.y()); //v6
} //V6
} //V5
starsPainted = true; //V5
/************************************************************************** V5
***** MOTIF-specific code - END ***** V5
**************************************************************************/ //V5
#endif //V5
#ifdef IC_PM //V5
/************************************************************************** V5
***** PM-specific code - BEGIN ***** V5
**************************************************************************/ //V5
/*----------------------------- Draw the Stars ---------------------------| V5
| Draw the stars by setting the foreground color to white and calling | V5
| the PM graphics functions for drawing points. | V5
|------------------------------------------------------------------------*/ //V5
POINTL //V5
ptlist[5]; //v6
GpiSetMarker(hps, MARKSYM_DOT) ; //V5
for (i=0;i<stars;i++) //V5
{ //V5
GpiSetColor(hps, starColor.index()) ; //V5
for(j=0;j<5;j++) //V6
{ //V6
ptlist[j]=star[i].point(j).asPOINTL(); //v6
} //V6
if (star[i].intensity()==dim) //V6
{ //V6
GpiPolyMarker(hps, 1, &ptlist[0]); //V5
GpiSetColor(hps, spaceColor.index()) ; //V6
GpiPolyMarker(hps, 4, &ptlist[1]); //V6
} //V6
else //V6
GpiPolyMarker(hps, 5, &ptlist[0]); //V6
} //V6
starsPainted = true; //V5
/************************************************************************** V5
***** PM-specific code - END ***** V5
**************************************************************************/ //V5
#endif //V5
return (starsPainted); //V5
} /* end AEarthWindow :: paintStars(...) */ //V5
/************************************************************************** V6
* AEarthWindow :: AStar :: AStar * V6
* Constructor for Earth window stars * V6
**************************************************************************/ //V6
AEarthWindow :: AStar :: AStar(IPair coordinates, Intensity starGlow) //v6
:currentIntensity(starGlow) //V6
{ //V6
/*--------------------------- Construct the Star -------------------------| V6
| Each star is constructed as five points. The first point is | v6
| constructed from the IPair passed in. The other four are created | v6
| by offsetting the first point by one in each direction; up, down, | V6
| left, and right. | V6
|------------------------------------------------------------------------*/ //V6
starPoint[0]=coordinates; //V6
starPoint[1]=starPoint[0]+IPair(0,1); //V6
starPoint[2]=starPoint[0]+IPair(1,0); //V6
starPoint[3]=starPoint[0]+IPair(0,-1); //V6
starPoint[4]=starPoint[0]+IPair(-1,0); //V6
if (currentIntensity==twinkle) //V6
{ //V6
if (flicker()) currentIntensity=bright; //V6
else currentIntensity=dim; //V6
} //V6
} /* end AEarthWindow :: AStar :: AStar(...) */ //V6
/************************************************************************** V6
* AEarthWindow :: AStar :: intensity * V6
* Return the current intensity of the star. * V6
**************************************************************************/ //V6
AEarthWindow::Intensity //V6
AEarthWindow :: AStar :: intensity() //V6
{ //V6
return (currentIntensity); //V6
} /* end AEarthWindow :: AStar :: intensity(...) */ //V6
/************************************************************************** V6
* AEarthWindow :: AStar :: point * V6
* Return star point. * V6
**************************************************************************/ //V6
const IPoint //V6
AEarthWindow :: AStar :: point(const unsigned long i) //V6
{ //V6
return starPoint[i]; //V6
} /* end AEarthWindow :: AStar :: point(...) */ //V6
/************************************************************************** V6
* AEarthWindow :: AStar :: flicker * V6
* Static function that randomly returns true or false. * V6
**************************************************************************/ //V6
IBase::Boolean //V6
AEarthWindow :: AStar :: flicker() //V6
{ //V6
Boolean flickered; //V6
if (rand()%2) flickered=true; //V6
else flickered=false; //V6
return (flickered); //V6
} /* end AEarthWindow :: AStar :: flicker() */ //V6
/************************************************************************** V6
* AEarthWindow :: enableBright * V6
* Set the star intensity to bright or dim. * V6
**************************************************************************/ //V6
AEarthWindow //V6
&AEarthWindow :: enableBright(IBase::Boolean makingBright) //V6
{ //V6
if (makingBright && starIntensity != bright) //V6
{ //V6
starIntensity = bright; //V6
refresh(); //V6
} //V6
else if (!makingBright && starIntensity != dim) //V6
{ //V6
starIntensity = dim; //V6
refresh(); //V6
} //V6
return (*this); //V6
} /* end AEarthWindow :: enableBright */ //V6
/************************************************************************** V6
* AEarthWindow :: disableBright * V6
* Set the star intensity to dim. * V6
**************************************************************************/ //V6
AEarthWindow //V6
&AEarthWindow :: disableBright() //V6
{ //V6
return (enableBright(false)); //V6
} /* end AEarthWindow :: disableBright */ //V6
/************************************************************************** V6
* AEarthWindow :: isBright * V6
* Return true if starIntensity is bright, else return false. * V6
**************************************************************************/ //V6
const IBase::Boolean //V6
AEarthWindow :: isBright() //V6
{ //V6
return (starIntensity==bright); //V6
} /* end AEarthWindow :: isBright */ //V6
/************************************************************************** V6
* AEarthWindow :: setLayers * V6
* Set the atmosphere layers to 0, 1, 2, or 3. * V6
**************************************************************************/ //V6
AEarthWindow //V6
&AEarthWindow :: setLayers(const unsigned long layers) //V6
{ //V6
if(layers>=3) atmosphereLayers=3; //V6
else atmosphereLayers=layers; //V6
refresh(); //V6
return (*this); //V6
} /* end AEarthWindow :: setLayers */ //V6
/************************************************************************** V6
* AEarthWindow :: layers * V6
* Return the current number of layers of atmosphere. * V6
**************************************************************************/ //V6
const unsigned long //V6
AEarthWindow :: layers() //V6
{ //V6
return (atmosphereLayers); //V6
} /* end AEarthWindow :: layers */ //V6
/************************************************************************** V6
* AEarthWindow :: enableTwinkle * V6
* Make the stars twinkle. * V6
**************************************************************************/ //V6
AEarthWindow //V6
&AEarthWindow :: enableTwinkle(IBase::Boolean turningOn) //V6
{ //V6
if (turningOn && !twinkling) //V6
{ //V6
twinkling=true; //V6
twinkleHandler.handleEventsFor(this); //V6
} //V6
else if (!turningOn && twinkling) //V6
{ //V6
twinkling=false; //V6
twinkleHandler.stopHandlingEventsFor(this); //V6
} //V6
refresh(); //V6
return (*this); //V6
} /* end AEarthWindow :: enableTwinkle (...) */ //V6
/************************************************************************** V6
* AEarthWindow :: disableTwinkle * V6
* Make the stars stop twinkling. * V6
**************************************************************************/ //V6
AEarthWindow //V6
&AEarthWindow :: disableTwinkle() //V6
{ //V6
return (enableTwinkle(false)); //V6
} /* end AEarthWindow :: disableTwinkle() */ //V6
/************************************************************************** V6
* AEarthWindow :: isTwinkling * V6
* Are the stars twinkling? Is twinkling == true ? * V6
**************************************************************************/ //V6
const IBase::Boolean //V6
AEarthWindow :: isTwinkling() //V6
{ //V6
return (twinkling); //V6
} /* end AEarthWindow :: disableTwinkle() */ //V6
/************************************************************************** V6
* AEarthWindow :: setEarthColor * V6
* Set the color used for drawing the inner arc that represents Earth. * V6
**************************************************************************/ //V6
AEarthWindow //V6
&AEarthWindow :: setEarthColor(const IColor &hue) //V6
{ //V6
globeColor = hue; //V6
refresh(); //V6
return (*this); //V6
} /* end AEarthWindow :: setEarthColor(...) */ //V6
/************************************************************************** V6
* AEarthWindow :: earthColor * V6
* Return the current color being used to draw the Earth. * V6
**************************************************************************/ //V6
const IColor //V6
&AEarthWindow :: earthColor() //V6
{ //V6
return (globeColor); //V6
} /* end AEarthWindow :: earthColor() */ //V6
/************************************************************************** V6
* ATwinkleTimeHandler :: tick * V6
* Process ATimeHandler ticks by calling the AEarthWindow function * V6
* for twinkling the stars. * V6
**************************************************************************/ //V6
IBase::Boolean //V6
ATwinkleTimeHandler::tick(IEvent& evt) //V6
{ //V6
((AEarthWindow *)evt.window())->paintStars(); //V6
return (true); //Event is always processed V6
} //V6