123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- // Original header:
- // GuiMaterialPreview Control for Material Editor Written by Travis Vroman of Gaslight Studios
- // Updated 2-14-09
- // Portions based off Constructor viewport code.
- #include "console/engineAPI.h"
- #include "T3D/guiMaterialPreview.h"
- #include "renderInstance/renderPassManager.h"
- #include "lighting/lightManager.h"
- #include "lighting/lightInfo.h"
- #include "core/resourceManager.h"
- #include "scene/sceneManager.h"
- #include "scene/sceneRenderState.h"
- // GuiMaterialPreview
- GuiMaterialPreview::GuiMaterialPreview()
- : mMouseState(None),
- mModel(NULL),
- runThread(0),
- lastRenderTime(0),
- mLastMousePoint(0, 0),
- mFakeSun(NULL),
- mMaxOrbitDist(5.0f),
- mMinOrbitDist(0.0f),
- mOrbitDist(5.0f)
- {
- mActive = true;
- mCameraMatrix.identity();
- mCameraRot.set( mDegToRad(30.0f), 0, mDegToRad(-30.0f) );
- mCameraPos.set(0.0f, 1.75f, 1.25f);
- mCameraMatrix.setColumn(3, mCameraPos);
- mOrbitPos.set(0.0f, 0.0f, 0.0f);
- mTransStep = 0.01f;
- mTranMult = 4.0;
- mLightTransStep = 0.01f;
- mLightTranMult = 4.0;
- mOrbitRelPos = Point3F(0,0,0);
- // By default don't do dynamic reflection
- // updates for this viewport.
- mReflectPriority = 0.0f;
- mMountedModel = NULL;
- mSkinTag = 0;
- }
- GuiMaterialPreview::~GuiMaterialPreview()
- {
- SAFE_DELETE(mModel);
- SAFE_DELETE(mFakeSun);
- }
- bool GuiMaterialPreview::onWake()
- {
- if( !Parent::onWake() )
- return false;
- if (!mFakeSun)
- mFakeSun = LightManager::createLightInfo();
- mFakeSun->setColor( LinearColorF( 1.0f, 1.0f, 1.0f ) );
- mFakeSun->setAmbient( LinearColorF( 0.5f, 0.5f, 0.5f ) );
- mFakeSun->setDirection( VectorF( 0.0f, 0.707f, -0.707f ) );
- mFakeSun->setPosition( mFakeSun->getDirection() * -10000.0f );
- mFakeSun->setRange( 2000000.0f );
- return true;
- }
- // This function allows the viewport's ambient color to be changed. This is exposed to script below.
- void GuiMaterialPreview::setAmbientLightColor( F32 r, F32 g, F32 b )
- {
- LinearColorF temp(r, g, b);
- temp.clamp();
- GuiMaterialPreview::mFakeSun->setAmbient( temp );
- }
- // This function allows the light's color to be changed. This is exposed to script below.
- void GuiMaterialPreview::setLightColor( F32 r, F32 g, F32 b )
- {
- LinearColorF temp(r, g, b);
- temp.clamp();
- GuiMaterialPreview::mFakeSun->setColor( temp );
- }
- // This function is for moving the light in the scene. This needs to be adjusted to keep the light
- // from getting all out of whack. For now, we'll just rely on the reset function if we need it
- // fixed.
- void GuiMaterialPreview::setLightTranslate(S32 modifier, F32 xstep, F32 ystep)
- {
- F32 _lighttransstep = (modifier & SI_SHIFT ? mLightTransStep : (mLightTransStep*mLightTranMult));
- Point3F relativeLightDirection = GuiMaterialPreview::mFakeSun->getDirection();
- // May be able to get rid of this. For now, it helps to fix the position of the light if i gets messed up.
- if (modifier & SI_PRIMARY_CTRL)
- {
- relativeLightDirection.x += ( xstep * _lighttransstep * -1 );//need to invert this for some reason. Otherwise, it's backwards.
- relativeLightDirection.y += ( ystep * _lighttransstep );
- GuiMaterialPreview::mFakeSun->setDirection(relativeLightDirection);
- }
- // Default action taken by mouse wheel clicking.
- else
- {
- relativeLightDirection.x += ( xstep * _lighttransstep * -1 ); //need to invert this for some reason. Otherwise, it's backwards.
- relativeLightDirection.z += ( ystep * _lighttransstep );
- GuiMaterialPreview::mFakeSun->setDirection(relativeLightDirection);
- }
- }
- // This is for panning the viewport camera.
- void GuiMaterialPreview::setTranslate(S32 modifier, F32 xstep, F32 ystep)
- {
- F32 transstep = (modifier & SI_SHIFT ? mTransStep : (mTransStep*mTranMult));
- F32 nominalDistance = 20.0;
- Point3F vec = mCameraPos;
- vec -= mOrbitPos;
- transstep *= vec.len() / nominalDistance;
- if (modifier & SI_PRIMARY_CTRL)
- {
- mOrbitRelPos.x += ( xstep * transstep );
- mOrbitRelPos.y += ( ystep * transstep );
- }
- else
- {
- mOrbitRelPos.x += ( xstep * transstep );
- mOrbitRelPos.z += ( ystep * transstep );
- }
- }
- // Left Click
- void GuiMaterialPreview::onMouseDown(const GuiEvent &event)
- {
- mMouseState = MovingLight;
- mLastMousePoint = event.mousePoint;
- mouseLock();
- }
- // Left Click Release
- void GuiMaterialPreview::onMouseUp(const GuiEvent &event)
- {
- mouseUnlock();
- mMouseState = None;
- }
- // Left Click Drag
- void GuiMaterialPreview::onMouseDragged(const GuiEvent &event)
- {
- if(mMouseState != MovingLight)
- {
- return;
- }
- // If we are MovingLight...
- else
- {
- Point2I delta = event.mousePoint - mLastMousePoint;
- mLastMousePoint = event.mousePoint;
- setLightTranslate(event.modifier, delta.x, delta.y);
- }
- }
- // Right Click
- void GuiMaterialPreview::onRightMouseDown(const GuiEvent &event)
- {
- mMouseState = Rotating;
- mLastMousePoint = event.mousePoint;
- mouseLock();
- }
- // Right Click Release
- void GuiMaterialPreview::onRightMouseUp(const GuiEvent &event)
- {
- mouseUnlock();
- mMouseState = None;
- }
- // Right Click Drag
- void GuiMaterialPreview::onRightMouseDragged(const GuiEvent &event)
- {
- if (mMouseState != Rotating)
- {
- return;
- }
- Point2I delta = event.mousePoint - mLastMousePoint;
- mLastMousePoint = event.mousePoint;
- mCameraRot.x += (delta.y * 0.01f);
- mCameraRot.z += (delta.x * 0.01f);
- }
- // Mouse Wheel Scroll Up
- bool GuiMaterialPreview::onMouseWheelUp(const GuiEvent &event)
- {
- mOrbitDist = (mOrbitDist - 0.10f);
- return true;
- }
- // Mouse Wheel Scroll Down
- bool GuiMaterialPreview::onMouseWheelDown(const GuiEvent &event)
- {
- mOrbitDist = (mOrbitDist + 0.10f);
- return true;
- }
- // Mouse Wheel Click
- void GuiMaterialPreview::onMiddleMouseDown(const GuiEvent &event)
- {
- if (!mActive || !mVisible || !mAwake)
- {
- return;
- }
- mMouseState = Panning;
- mLastMousePoint = event.mousePoint;
- mouseLock();
- }
- // Mouse Wheel Click Release
- void GuiMaterialPreview::onMiddleMouseUp(const GuiEvent &event)
- {
- mouseUnlock();
- mMouseState = None;
- }
- // Mouse Wheel Click Drag
- void GuiMaterialPreview::onMiddleMouseDragged(const GuiEvent &event)
- {
- if (mMouseState != Panning)
- {
- return;
- }
- Point2I delta = event.mousePoint - mLastMousePoint;
- mLastMousePoint = event.mousePoint;
- setTranslate(event.modifier, delta.x, delta.y);
- }
- // This is used to set the model we want to view in the control object.
- void GuiMaterialPreview::setObjectModel(const char* modelName)
- {
- deleteModel();
- Resource<TSShape> model = ResourceManager::get().load(modelName);
- if (! bool(model))
- {
- Con::warnf(avar("GuiMaterialPreview: Failed to load model %s. Please check your model name and load a valid model.", modelName));
- return;
- }
- mModel = new TSShapeInstance(model, true);
- AssertFatal(mModel, avar("GuiMaterialPreview: Failed to load model %s. Please check your model name and load a valid model.", modelName));
- // Initialize camera values:
- mOrbitPos = mModel->getShape()->center;
- mMinOrbitDist = mModel->getShape()->mRadius;
- lastRenderTime = Platform::getVirtualMilliseconds();
- }
- void GuiMaterialPreview::deleteModel()
- {
- SAFE_DELETE(mModel);
- runThread = 0;
- }
- // This is called whenever there is a change in the camera.
- bool GuiMaterialPreview::processCameraQuery(CameraQuery* query)
- {
- MatrixF xRot, zRot;
- Point3F vecf, vecu, vecr;;
- xRot.set(EulerF(mCameraRot.x, 0.0f, 0.0f));
- zRot.set(EulerF(0.0f, 0.0f, mCameraRot.z));
- if(mMouseState != Panning)
- {
- // Adjust the camera so that we are still facing the model:
- Point3F vec;
- mCameraMatrix.mul(zRot, xRot);
- mCameraMatrix.getColumn(1, &vec);
- vec *= mOrbitDist;
- mCameraPos = mOrbitPos - vec;
- query->farPlane = 2100.0f;
- query->nearPlane = query->farPlane / 5000.0f;
- query->fov = 45.0f;
- mCameraMatrix.setColumn(3, mCameraPos);
- query->cameraMatrix = mCameraMatrix;
- }
- else
- {
- mCameraMatrix.mul( zRot, xRot );
- mCameraMatrix.getColumn( 1, &vecf ); // Forward vector
- mCameraMatrix.getColumn( 2, &vecu ); // Up vector
- mCameraMatrix.getColumn( 0, &vecr ); // Right vector
- Point3F flatVecf(vecf.x, vecf.y, 0.0f);
- Point3F modvecf = flatVecf * mOrbitRelPos.y;
- Point3F modvecu = vecu * mOrbitRelPos.z;
- Point3F modvecr = vecr * mOrbitRelPos.x;
- // Change the orbit position
- mOrbitPos += modvecu - modvecr + modvecf;
- F32 vecfmul = mOrbitDist;
- Point3F virtualVecF = vecf * mOrbitDist;
- vecf *= vecfmul;
- mCameraPos = mOrbitPos - virtualVecF;
- // Update the camera's position
- mCameraMatrix.setColumn( 3, (mOrbitPos - vecf) );
- query->farPlane = 2100.0f;
- query->nearPlane = query->farPlane / 5000.0f;
- query->fov = 45.0f;
- query->cameraMatrix = mCameraMatrix;
- // Reset the relative position
- mOrbitRelPos = Point3F(0,0,0);
- }
- return true;
- }
- void GuiMaterialPreview::onMouseEnter(const GuiEvent & event)
- {
- Con::executef(this, "onMouseEnter");
- }
- void GuiMaterialPreview::onMouseLeave(const GuiEvent & event)
- {
- Con::executef(this, "onMouseLeave");
- }
- void GuiMaterialPreview::renderWorld(const RectI &updateRect)
- {
- // nothing to render, punt
- if ( !mModel && !mMountedModel )
- return;
- S32 time = Platform::getVirtualMilliseconds();
- //S32 dt = time - lastRenderTime;
- lastRenderTime = time;
-
- F32 left, right, top, bottom, nearPlane, farPlane;
- bool isOrtho;
- GFX->getFrustum( &left, &right, &bottom, &top, &nearPlane, &farPlane, &isOrtho);
- Frustum frust( isOrtho, left, right, bottom, top, nearPlane, farPlane, MatrixF::Identity );
- FogData savedFogData = gClientSceneGraph->getFogData();
- gClientSceneGraph->setFogData( FogData() ); // no fog in preview window
- RenderPassManager* renderPass = gClientSceneGraph->getDefaultRenderPass();
- SceneRenderState state
- (
- gClientSceneGraph,
- SPT_Diffuse,
- SceneCameraState( GFX->getViewport(), frust, GFX->getWorldMatrix(), GFX->getProjectionMatrix() ),
- renderPass,
- true
- );
- // Set up our TS render state here.
- TSRenderState rdata;
- rdata.setSceneState( &state );
- // We might have some forward lit materials
- // so pass down a query to gather lights.
- LightQuery query;
- query.init( SphereF( Point3F::Zero, 1.0f ) );
- rdata.setLightQuery( &query );
- // Set up pass transforms
- renderPass->assignSharedXform(RenderPassManager::View, MatrixF::Identity);
- renderPass->assignSharedXform(RenderPassManager::Projection, GFX->getProjectionMatrix());
- LIGHTMGR->unregisterAllLights();
- LIGHTMGR->setSpecialLight( LightManager::slSunLightType, mFakeSun );
- if ( mModel )
- mModel->render( rdata );
- if ( mMountedModel )
- {
- // render a weapon
- /*
- MatrixF mat;
- GFX->pushWorldMatrix();
- GFX->multWorld( mat );
- GFX->popWorldMatrix();
- */
- }
- renderPass->renderPass( &state );
- gClientSceneGraph->setFogData( savedFogData ); // restore fog setting
- // Make sure to remove our fake sun
- LIGHTMGR->unregisterAllLights();
- }
- // Make sure the orbit distance is within the acceptable range.
- void GuiMaterialPreview::setOrbitDistance(F32 distance)
- {
- mOrbitDist = mClampF(distance, mMinOrbitDist, mMaxOrbitDist);
- }
- // This function is meant to be used with a button to put everything back to default settings.
- void GuiMaterialPreview::resetViewport()
- {
- // Reset the camera's orientation.
- mCameraRot.set( mDegToRad(30.0f), 0, mDegToRad(-30.0f) );
- mCameraPos.set(0.0f, 1.75f, 1.25f);
- mOrbitDist = 5.0f;
- mOrbitPos = mModel->getShape()->center;
- // Reset the viewport's lighting.
- GuiMaterialPreview::mFakeSun->setColor( LinearColorF( 1.0f, 1.0f, 1.0f ) );
- GuiMaterialPreview::mFakeSun->setAmbient( LinearColorF( 0.5f, 0.5f, 0.5f ) );
- GuiMaterialPreview::mFakeSun->setDirection( VectorF( 0.0f, 0.707f, -0.707f ) );
- }
- // Expose the class and functions to the console.
- IMPLEMENT_CONOBJECT(GuiMaterialPreview);
- ConsoleDocClass( GuiMaterialPreview,
- "@brief Visual preview of a specified Material\n\n"
- "Editor use only.\n\n"
- "@internal"
- );
- // Set the model.
- DefineEngineMethod(GuiMaterialPreview, setModel, void, ( const char* shapeName ),,
- "Sets the model to be displayed in this control\n\n"
- "@param shapeName Name of the model to display.\n")
- {
- object->setObjectModel(shapeName);
- }
- DefineEngineMethod(GuiMaterialPreview, deleteModel, void, (),,
- "Deletes the preview model.\n")
- {
- object->deleteModel();
- }
- // Set orbit distance around the model.
- DefineEngineMethod(GuiMaterialPreview, setOrbitDistance, void, ( F32 distance ),,
- "Sets the distance at which the camera orbits the object. Clamped to the "
- "acceptable range defined in the class by min and max orbit distances.\n\n"
- "@param distance The distance to set the orbit to (will be clamped).")
- {
- object->setOrbitDistance(distance);
- }
- // Reset control to default values. Meant to be used with a button.
- DefineEngineMethod(GuiMaterialPreview, reset, void, (),,
- "Resets the viewport to default zoom, pan, rotate and lighting.")
- {
- object->resetViewport();
- }
- // This function allows the user to change the light's color.
- DefineEngineMethod(GuiMaterialPreview, setLightColor, void, ( LinearColorF color ),,
- "Sets the color of the light in the scene.\n")
- {
- object->setLightColor( color.red, color.green, color.blue );
- }
- // This function allows the user to change the viewports's ambient color.
- DefineEngineMethod(GuiMaterialPreview, setAmbientLightColor, void, ( LinearColorF color ),,
- "Sets the color of the ambient light in the scene.\n")
- {
- object->setAmbientLightColor( color.red, color.green, color.blue );
- }
|