dhewm3/neo/tools/materialeditor/MaterialPreviewView.cpp
Daniel Gibson 9a95a2a1cf Building with editor support (on Win w/ VS2017) works \o/
Editor also seems to start, didn't test much further.

Only tested 32bit Windows, I fear the editor code isn't 64bit clean..

I hope I haven't broken anything elsewhere..
2019-01-13 22:52:28 +01:00

654 lines
16 KiB
C++

/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "tools/edit_gui_common.h"
#include "../radiant/QE3.H"
#include "MaterialPreviewView.h"
// MaterialPreviewView
IMPLEMENT_DYNCREATE(MaterialPreviewView, CView)
MaterialPreviewView::MaterialPreviewView() {
// Initialize the rendered material
renderedView.setMedia( "_default" );
}
MaterialPreviewView::~MaterialPreviewView() {
}
BEGIN_MESSAGE_MAP(MaterialPreviewView, CView)
ON_WM_CREATE()
ON_WM_SIZE()
END_MESSAGE_MAP()
// MaterialPreviewView drawing
void MaterialPreviewView::OnDraw(CDC* pDC) {
}
// MaterialPreviewView diagnostics
#ifdef _DEBUG
void MaterialPreviewView::AssertValid() const {
CView::AssertValid();
}
void MaterialPreviewView::Dump(CDumpContext& dc) const {
CView::Dump(dc);
}
#endif //_DEBUG
// MaterialPreviewView message handlers
int MaterialPreviewView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
DWORD dwStyle;
CRect rc;
dwStyle = WS_CHILD|WS_VISIBLE;
// Init the control's size to cover the entire client area
GetClientRect(rc);
// Initialize the rendered window and material
renderWindow.Create( NULL, "renderWindow", dwStyle, rc, this, 1010 );
renderWindow.setDrawable( &renderedView );
renderWindow.SetWindowPos(NULL, 0, 0, rc.Width(), rc.Height(), SWP_SHOWWINDOW);
return 0;
}
void MaterialPreviewView::OnSize(UINT nType, int cx, int cy)
{
CRect rc;
CView::OnSize( nType, cx, cy );
GetClientRect( rc );
renderWindow.SetWindowPos(NULL, 0, 0, rc.Width(), rc.Height(), SWP_SHOWWINDOW);
renderWindow.Invalidate();
renderWindow.RedrawWindow();
}
void MaterialPreviewView::MV_OnMaterialSelectionChange( MaterialDoc *pMaterial )
{
if ( pMaterial && pMaterial->renderMaterial ) {
currentMaterial = pMaterial->renderMaterial->GetName();
renderedView.setMedia( currentMaterial );
renderWindow.Invalidate();
renderWindow.RedrawWindow();
}
}
void MaterialPreviewView::OnLocalParmChange( int parmNum, float value ) {
renderedView.setLocalParm( parmNum, value );
}
void MaterialPreviewView::OnGlobalParmChange( int parmNum, float value ) {
renderedView.setGlobalParm( parmNum, value );
}
void MaterialPreviewView::OnLightShaderChange( int lightId, idStr shaderName ) {
renderedView.setLightShader( lightId, shaderName );
}
void MaterialPreviewView::OnLightColorChange( int lightId, idVec3 &color ) {
renderedView.setLightColor( lightId, color );
}
void MaterialPreviewView::OnLightRadiusChange( int lightId, float radius ) {
renderedView.setLightRadius( lightId, radius );
}
void MaterialPreviewView::OnLightAllowMoveChange( int lightId, bool move ) {
renderedView.setLightAllowMove( lightId, move );
}
void MaterialPreviewView::OnAddLight( void ) {
renderedView.addLight();
}
void MaterialPreviewView::OnDeleteLight( int lightId ) {
renderedView.deleteLight( lightId );
}
void MaterialPreviewView::OnModelChange( int modelId ) {
renderedView.setObject( modelId );
}
void MaterialPreviewView::OnCustomModelChange( idStr modelName ) {
renderedView.setCustomModel( modelName );
}
void MaterialPreviewView::OnShowLightsChange( bool showLights ) {
renderedView.setShowLights( showLights );
}
/*
=============================================================================
=============================================================================
=============================================================================
*/
extern bool Sys_KeyDown(int key);
extern float fDiff(float f1, float f2);
idGLDrawableView::idGLDrawableView() {
material = NULL;
modelDefHandle = -1;
objectId = 0;
showLights = true;
realTime = 16;
viewOrigin.Set( 0.f, 0.f, 0.f );
viewRotation.Set( 0.f, 0.f, 0.f );
viewDistance = -196.f;
world = NULL;
worldModel = NULL;
ResetView();
}
idGLDrawableView::~idGLDrawableView() {
delete world;
delete worldModel;
}
void idGLDrawableView::ResetView( void ) {
idDict spawnArgs;
InitWorld();
memset( &worldEntity, 0, sizeof( worldEntity ) );
spawnArgs.Clear();
spawnArgs.Set("classname", "func_static");
spawnArgs.Set("name", spawnArgs.GetString("model"));
spawnArgs.Set("origin", "0 0 0");
gameEdit->ParseSpawnArgsToRenderEntity(&spawnArgs, &worldEntity);
// load a model and set the current material as its customshader
worldModel = renderModelManager->FindModel("models/materialeditor/cube128.ase");
worldEntity.hModel = worldModel;
// current material
worldEntity.customShader = material;
// current rotation
worldEntity.axis = mat3_identity;
// set global shader parms
memset( globalParms, 0, sizeof( globalParms ) );
globalParms[0] = globalParms[1] = globalParms[2] = globalParms[3] = 1.f;
worldEntity.shaderParms[0] = 1.f;
worldEntity.shaderParms[1] = 1.f;
worldEntity.shaderParms[2] = 1.f;
worldEntity.shaderParms[3] = 1.f;
modelDefHandle = world->AddEntityDef( &worldEntity );
}
void idGLDrawableView::InitWorld() {
if ( world == NULL ) {
world = renderSystem->AllocRenderWorld();
}
if ( worldModel == NULL ) {
worldModel = renderModelManager->AllocModel();
}
world->InitFromMap( NULL );
worldModel->InitEmpty( "GLWorldModel" );
viewLights.Clear();
}
void idGLDrawableView::buttonDown(int _button, float x, float y) {
pressX = x;
pressY = y;
button = _button;
if ( button == MK_RBUTTON || button == MK_LBUTTON || button == MK_MBUTTON ) {
handleMove = true;
}
}
void idGLDrawableView::mouseMove(float x, float y) {
bool doZoom;
float sensitivity = 0.5f;
if (handleMove) {
// Left mouse button rotates and zooms the view
if (button == MK_LBUTTON) {
doZoom = Sys_KeyDown(VK_MENU);
if (doZoom) {
if ( y != pressY ) {
viewDistance -= ( y - pressY );
pressY = y;
}
} else {
float xo = 0.f;
float yo = 0.f;
if (x != pressX) {
xo = (x - pressX);
pressX = x;
}
if (y != pressY) {
yo = (y - pressY);
pressY = y;
}
viewRotation.yaw += -(xo * sensitivity);
viewRotation.pitch += (yo * sensitivity);
viewRotation.pitch = idMath::ClampFloat( -89.9f, 89.9f, viewRotation.pitch );
}
// Right mouse button moves lights in the view plane
} else if (button == MK_RBUTTON) {
int i;
float lightMovement = 0;
idVec3 lightForward, lightRight, lightUp;
idVec3 lightMove;
lightMove.Zero();
viewRotation.ToVectors( &lightForward, &lightRight, &lightUp );
doZoom = Sys_KeyDown(VK_MENU);
if (doZoom) {
if ( y != pressY ) {
lightMovement = -( y - pressY ) * sensitivity;
pressY = y;
lightMovement = idMath::ClampFloat( -32.f, 32.f, lightMovement );
lightMove = lightForward * lightMovement;
}
} else {
if (x != pressX) {
lightMovement = (x - pressX) * sensitivity;
pressX = x;
lightMovement = idMath::ClampFloat( -32.f, 32.f, lightMovement );
lightMove = lightRight * lightMovement;
}
if (y != pressY) {
lightMovement = -(y - pressY) * sensitivity;
pressY = y;
lightMovement = idMath::ClampFloat( -32.f, 32.f, lightMovement );
lightMove += lightUp * lightMovement;
}
}
// Go through the lights and move the ones that are set to allow movement
for ( i = 0; i < viewLights.Num(); i++ ) {
lightInfo_t *vLight = &viewLights[i];
if ( vLight->allowMove ) {
vLight->origin += lightMove;
}
}
// Middle mouse button moves object up and down
} else if ( button == MK_MBUTTON ) {
float yo = 0.f;
if (y != pressY) {
yo = (y - pressY);
pressY = y;
}
viewOrigin.z -= yo;
UpdateModel();
}
}
}
void idGLDrawableView::addLight( void ) {
int lightId;
idStr str;
lightInfo_t viewLight;
idDict spawnArgs;
lightId = viewLights.Num();
spawnArgs.Set( "classname", "light" );
spawnArgs.Set( "name", va( "light_%d", lightId ) );
spawnArgs.Set( "origin", va( "-128 0 %d", (lightId * 16) ) );
spawnArgs.Set( "light", "300" );
spawnArgs.Set( "texture", "lights/defaultPointLight" );
sprintf( str, "%f %f %f", 1.f, 1.f, 1.f );
spawnArgs.Set( "_color", str );
gameEdit->ParseSpawnArgsToRenderLight( &spawnArgs, &viewLight.renderLight );
viewLight.lightDefHandle = world->AddLightDef( &viewLight.renderLight );
viewLight.origin = viewLight.renderLight.origin;
viewLight.shader = declManager->FindMaterial( "lights/defaultPointLight", false );
viewLight.color.x = viewLight.renderLight.shaderParms[ SHADERPARM_RED ];
viewLight.color.y = viewLight.renderLight.shaderParms[ SHADERPARM_GREEN ];
viewLight.color.z = viewLight.renderLight.shaderParms[ SHADERPARM_BLUE ];
viewLight.radius = 300.f;
viewLight.allowMove = true;
// Add light to the list
viewLights.Append( viewLight );
}
void idGLDrawableView::deleteLight( const int lightId ) {
if ( lightId < viewLights.Num() ) {
world->FreeLightDef( viewLights[lightId].lightDefHandle );
viewLights.RemoveIndex( lightId );
}
}
void idGLDrawableView::UpdateCamera( renderView_t *refdef ) {
idVec3 pos, dir;
idAngles angs;
// Set the camera origin
pos = viewRotation.ToForward();
pos *= viewDistance;
refdef->vieworg = pos;
// Set the view to point back at the origin
dir = vec3_origin - pos;
angs = dir.ToAngles();
refdef->viewaxis = angs.ToMat3();
}
void idGLDrawableView::UpdateModel( void ) {
switch( objectId ) {
case 0:
worldModel = renderModelManager->FindModel("models/materialeditor/cube128.ase");
break;
case 1:
worldModel = renderModelManager->FindModel("models/materialeditor/box128x64.ase");
break;
case 2:
worldModel = renderModelManager->FindModel("models/materialeditor/box128x32.ase");
break;
case 3:
worldModel = renderModelManager->FindModel("models/materialeditor/box64x128.ase");
break;
case 4:
worldModel = renderModelManager->FindModel("models/materialeditor/box32x128.ase");
break;
case 5:
worldModel = renderModelManager->FindModel("models/materialeditor/cylinder_v.ase");
break;
case 6:
worldModel = renderModelManager->FindModel("models/materialeditor/cylinder_h.ase");
break;
case 7:
worldModel = renderModelManager->FindModel("models/materialeditor/sphere64.ase");
break;
case -1:
worldModel = renderModelManager->FindModel( customModelName.c_str() );
break;
default:
worldModel = renderModelManager->FindModel("models/materialeditor/cube128.ase");
break;
};
worldEntity.hModel = worldModel;
// current material
worldEntity.customShader = material;
// current rotation
worldEntity.origin = viewOrigin;
worldEntity.axis = mat3_identity;
world->UpdateEntityDef( modelDefHandle, &worldEntity );
}
void idGLDrawableView::UpdateLights( void ) {
int i;
for ( i = 0; i < viewLights.Num(); i++ ) {
lightInfo_t *vLight = &viewLights[i];
vLight->renderLight.shader = vLight->shader;
vLight->renderLight.shaderParms[ SHADERPARM_RED ] = vLight->color.x;
vLight->renderLight.shaderParms[ SHADERPARM_GREEN ] = vLight->color.y;
vLight->renderLight.shaderParms[ SHADERPARM_BLUE ] = vLight->color.z;
vLight->renderLight.lightRadius[0] = vLight->renderLight.lightRadius[1] =
vLight->renderLight.lightRadius[2] = vLight->radius;
vLight->renderLight.origin = vLight->origin;
world->UpdateLightDef( vLight->lightDefHandle, &vLight->renderLight );
}
}
void idGLDrawableView::drawLights( renderView_t *refdef ) {
int i;
for ( i=0; i < viewLights.Num(); i++ ) {
lightInfo_t *vLight = &viewLights[i];
idVec4 lColor;
lColor.x = vLight->color.x;
lColor.y = vLight->color.y;
lColor.z = vLight->color.z;
lColor.w = 1.f;
idSphere sphere(vLight->renderLight.origin, 4);
session->rw->DebugSphere( lColor, sphere, 0, true );
session->rw->DrawText( va( "%d", i+1 ), vLight->renderLight.origin + idVec3(0,0,5), 0.25f, idVec4(1,1,0,1), refdef->viewaxis, 1, 0, true );
}
}
void idGLDrawableView::draw(int x, int y, int w, int h) {
int i;
renderView_t refdef;
const idMaterial *mat = material;
if (mat) {
qglViewport(x, y, w, h);
qglScissor(x, y, w, h);
qglMatrixMode(GL_PROJECTION);
qglClearColor( 0.1f, 0.1f, 0.1f, 0.0f );
qglClear(GL_COLOR_BUFFER_BIT);
UpdateLights();
// render it
renderSystem->BeginFrame(w, h);
memset( &refdef, 0, sizeof( refdef ) );
UpdateCamera( &refdef );
// Copy global shaderparms to view
for( i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ ) {
refdef.shaderParms[ i ] = globalParms[ i ];
}
refdef.width = SCREEN_WIDTH;
refdef.height = SCREEN_HEIGHT;
refdef.fov_x = 90;
refdef.fov_y = 2 * atan((float)h / w) * idMath::M_RAD2DEG;
refdef.time = eventLoop->Milliseconds();
world->RenderScene( &refdef );
if ( showLights ) {
drawLights( &refdef );
}
renderSystem->EndFrame( NULL, NULL );
world->DebugClearLines( refdef.time );
qglMatrixMode( GL_MODELVIEW );
qglLoadIdentity();
}
}
// ============================
// Interface to PropTree Window
// ============================
void idGLDrawableView::setMedia(const char *name) {
float ratio = 1;
if (name && *name) {
material = declManager->FindMaterial(name);
} else {
material = NULL;
}
if ( material->GetNumStages() == 0 ) {
material = declManager->FindMaterial( "_default" );
}
if ( material->GetStage(0)->texture.image ) {
ratio = (float)((float)material->GetImageWidth() / (float)material->GetImageHeight());
}
if ( objectId == -1 ) {
// Don't change a custom model
} else if ( ratio == 1 ) {
objectId = 0;
} else if ( ratio == 2 ) {
objectId = 1;
} else if ( ratio == 4 ) {
objectId = 2;
} else if ( ratio == 0.5 ) {
objectId = 3;
} else if ( ratio == 0.25 ) {
objectId = 4;
}
UpdateModel();
}
void idGLDrawableView::setLocalParm( int parmNum, float value ) {
if ( parmNum < 0 || parmNum >= MAX_ENTITY_SHADER_PARMS ) {
return;
}
worldEntity.shaderParms[ parmNum ] = value;
UpdateModel();
}
void idGLDrawableView::setGlobalParm( int parmNum, float value ) {
if ( parmNum < 0 || parmNum >= MAX_GLOBAL_SHADER_PARMS ) {
return;
}
globalParms[ parmNum ] = value;
}
void idGLDrawableView::setLightShader( const int lightId, const idStr shaderName ) {
if ( lightId < viewLights.Num() ) {
viewLights[ lightId ].shader = declManager->FindMaterial( shaderName, false );
}
}
void idGLDrawableView::setLightColor( const int lightId, const idVec3 &value ) {
if ( lightId < viewLights.Num() ) {
// Update this lights color
viewLights[ lightId ].color = value;
}
}
void idGLDrawableView::setLightRadius( const int lightId, const float radius ) {
if ( lightId < viewLights.Num() ) {
viewLights[ lightId ].radius = radius;
}
}
void idGLDrawableView::setLightAllowMove( const int lightId, const bool move ) {
if ( lightId < viewLights.Num() ) {
viewLights[ lightId ].allowMove = move;
}
}
void idGLDrawableView::setObject( int Id ) {
objectId = Id;
UpdateModel();
}
void idGLDrawableView::setCustomModel( const idStr modelName ) {
if ( modelName.Length() ) {
objectId = -1;
} else {
objectId = 0;
}
customModelName = modelName;
UpdateModel();
}
void idGLDrawableView::setShowLights( bool _showLights ) {
showLights = _showLights;
}