/*==LICENSE==* CyanWorlds.com Engine - MMOG client, server and tools Copyright (C) 2011 Cyan Worlds, Inc. This program 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. This program 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 this program. If not, see . You can contact Cyan Worlds, Inc. by email legal@cyan.com or by snail mail at: Cyan Worlds, Inc. 14617 N Newport Hwy Mead, WA 99021 *==LICENSE==*/ #include "HeadSpin.h" #include "plRealTimeLightBase.h" #include "iparamm2.h" #include "resource.h" #include "decomp.h" #include "hsv.h" #include "target.h" #include "../MaxPlasmaMtls/Layers/plLayerTex.h" #include "../MaxPlasmaMtls/Layers/plLayerTexBitmapPB.h" static int GetTargetPoint(TimeValue t, INode *inode, Point3& p) { Matrix3 tmat; if (inode->GetTargetTM(t,tmat)) { p = tmat.GetTrans(); return 1; } else return 0; } /////////////////////////////////////////////////////////////////////////////// //// plBaseLightProc Functions //////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // This class provides the base functionality for all the dialog procs for // the ParamBlock rollouts for each light void plBaseLightProc::ILoadComboBox( HWND hComboBox, const char *names[] ) { SendMessage(hComboBox, CB_RESETCONTENT, 0, 0); for (int i = 0; names[i]; i++) SendMessage(hComboBox, CB_ADDSTRING, 0, (LPARAM)names[i]); SendMessage(hComboBox, CB_SETCURSEL, 0, 0); } void plBaseLightProc::IBuildLightMesh( plRTLightBase *base, float coneSize ) { base->BuildSpotMesh( coneSize ); base->fMesh = base->spotMesh; } BOOL plBaseLightProc::DlgProc( TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) { IParamBlock2 *pb = map->GetParamBlock(); plRTLightBase *gl = (plRTLightBase *) pb->GetOwner(); switch( msg ) { case WM_INITDIALOG: { HWND DecayTypeCombo = GetDlgItem(hWnd, IDC_LIGHT_DECAY); HWND ShadowStateCombo = GetDlgItem(hWnd, IDC_SHADOW_TYPE); map->Invalidate(plRTLightBase::kProjMapTexButton); } break; case WM_COMMAND: break; } return false; } /////////////////////////////////////////////////////////////////////////////// //// plLightTexPBAccessor Class Functions ///////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// plLightTexPBAccessor plLightTexPBAccessor::fAccessor; void plLightTexPBAccessor::Set( PB2Value& val, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t ) { plRTLightBase* Obj = (plRTLightBase*)owner; IParamBlock2 *pb = Obj->fLightPB; switch (id) { case plRTLightBase::kProjMapTexButton: if (1) //(val.bm)->bm) { if (pb->GetMap()) pb->GetMap()->Invalidate(plRTLightBase::kProjMapTexButton); //pb->SetValue(plRTLightBase::kProjMapTexButton, Obj->fIP->GetTime(), val.bm); PBBitmap* ThisMap = val.bm; Obj->SetProjMap(&ThisMap->bi); break; } default: break; } } void plLightTexPBAccessor::Get( PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t, Interval &valid ) { } //////////////////////////////////////////////////////////// // // Mouse creation callback class for this plug-in class RTLightMouseCallBack : public CreateMouseCallBack { plRTLightBase *ob; public: int proc(ViewExp *vpt, int msg, int point, int flags, IPoint2 m, Matrix3 &mat); void SetObj(plRTLightBase *obj) { ob = obj; } }; static RTLightMouseCallBack gRTMouseCallback; int RTLightMouseCallBack::proc(ViewExp *vpt, int msg, int point, int flags, IPoint2 m, Matrix3 &mat) { switch (msg) { case MOUSE_POINT: case MOUSE_MOVE: switch (point) { case 0: mat.SetTrans(vpt->SnapPoint(m,m,NULL,SNAP_IN_PLANE)); break; case 1: mat.SetTrans(vpt->SnapPoint(m,m,NULL,SNAP_IN_PLANE)); if (msg == MOUSE_POINT) return 0; break; } break; case MOUSE_ABORT: return CREATE_ABORT; } return CREATE_CONTINUE; } static RTLightMouseCallBack sRTBaseLgtCreateCB; CreateMouseCallBack* plRTLightBase::GetCreateMouseCallBack() { sRTBaseLgtCreateCB.SetObj(this); return &sRTBaseLgtCreateCB; } ///////////////////////////////////////////////////////////////////////////// #if 0 plRTLightBase::plRTLightBase() : fIP(nil), fClassDesc(nil), fLightPB(nil) { fColor = Color(0.5f, 0.5f, 1.f); } #endif void plRTLightBase::SetHSVColor(TimeValue t, Point3 &hsv) { DWORD rgb = HSVtoRGB ((int)(hsv[0]*255.0f), (int)(hsv[1]*255.0f), (int)(hsv[2]*255.0f)); Point3 temp = fLightPB->GetPoint3(kLightColor, t); Point3 rgbf; rgbf[0] = temp.x / 255.0f; rgbf[1] = temp.y / 255.0f; rgbf[2] = temp.z / 255.0f; SetRGBColor(t, rgbf); } Point3 plRTLightBase::GetHSVColor(TimeValue t, Interval& b) { int h, s, v; Point3 rgbf = GetRGBColor(t, b); DWORD rgb = RGB((int)(rgbf[0]*255.0f), (int)(rgbf[1]*255.0f), (int)(rgbf[2]*255.0f)); RGBtoHSV (rgb, &h, &s, &v); return Point3(h/255.0f, s/255.0f, v/255.0f); } #define FZ (0.0f) #define SET_QUAD(face, v0, v1, v2, v3) \ staticMesh[RT_OMNI +1].faces[face].setVerts(v0, v1, v2); \ staticMesh[RT_OMNI +1].faces[face].setEdgeVisFlags(1,1,0); \ staticMesh[RT_OMNI +1].faces[face+1].setVerts(v0, v2, v3); \ staticMesh[RT_OMNI +1].faces[face+1].setEdgeVisFlags(0,1,1); void plRTLightBase::BuildStaticMeshes() { if(!meshBuilt) { int nverts = 6; int nfaces = 8; // Build a leetle octahedron staticMesh[RT_OMNI].setNumVerts(nverts); staticMesh[RT_OMNI].setNumFaces(nfaces); float s = 8.0f; staticMesh[RT_OMNI].setVert(0, Point3( FZ,FZ, -s)); staticMesh[RT_OMNI].setVert(1, Point3( s, FZ, FZ)); staticMesh[RT_OMNI].setVert(2, Point3( FZ, s, FZ)); staticMesh[RT_OMNI].setVert(3, Point3(-s, FZ, FZ)); staticMesh[RT_OMNI].setVert(4, Point3( FZ,-s, FZ)); staticMesh[RT_OMNI].setVert(5, Point3( FZ,FZ, s)); staticMesh[RT_OMNI].faces[0].setVerts(0,1,4); staticMesh[RT_OMNI].faces[1].setVerts(0,4,3); staticMesh[RT_OMNI].faces[2].setVerts(0,3,2); staticMesh[RT_OMNI].faces[3].setVerts(0,2,1); staticMesh[RT_OMNI].faces[4].setVerts(5,1,2); staticMesh[RT_OMNI].faces[5].setVerts(5,2,3); staticMesh[RT_OMNI].faces[6].setVerts(5,3,4); staticMesh[RT_OMNI].faces[7].setVerts(5,4,1); for (int i=0; iID() ) return fLightPB; else return nil; } IParamBlock2 *plRTLightBase::GetParamBlock( int i ) { switch( i ) { case 0: return fLightPB; default: return nil; } } // So our animatables will show up in the trackview int plRTLightBase::NumSubs() { return 1; } Animatable *plRTLightBase::SubAnim(int i) { return (Animatable *)fLightPB; switch(i) { /* kRefProjMap, kRefShadowProjMap, kRefShadowType, kRefOmniLight, kRefSpotLight, kRefTSpotLight, kRefDirLight, kRefTDirLight */ case kRefOmniLight: case kRefSpotLight: case kRefTSpotLight: case kRefDirLight: case kRefTDirLight: case kRefProjDirLight: return (Animatable*)fLightPB; case kRefProjMap: Texmap* MyMap; return (Animatable*) fLightPB->GetValue(kProjMapTexButton, 0, MyMap, FOREVER); case kRefShadowType: return NULL; default: return NULL; } //return (Animatable*) fLightPB; } TSTR plRTLightBase::SubAnimName(int i) { return fLightPB->GetLocalName(); switch(i) { case kRefOmniLight:return _T(""); case kRefSpotLight: return TSTR(GetString(IDS_DB_FSPOT)); case kRefTSpotLight:return _T(""); case kRefDirLight:return _T(""); case kRefTDirLight:return _T(""); case kRefProjMap: return TSTR(GetString(IDS_DS_PROJMAP)); case kRefShadowType: return _T(""); default: return _T(""); /* case PBLOCK_REF: return TSTR(GetString(IDS_RB_PARAMETERS)); case PROJMAP_REF: return TSTR(GetString(IDS_DS_PROJMAP)); case SHADPROJMAP_REF: return TSTR(GetString(IDS_DS_SHADPROJMAP)); case SHADTYPE_REF: return TSTR(GetString(IDS_DS_SHAD_GEN)); case EMITTER_REF: if ( IsCompatibleRenderer ()) return TSTR(GetString(IDS_EMITTER)); else return _T(""); default: return _T(""); */ } } #if 0 RefTargetHandle plRTSpotLight::Clone(RemapDir &remap) { plRTLightBase *obj = TRACKED_NEW plRTSpotLight; obj->GetParamBlock2->SetValue(kLightOn, t, fLightPB->GetInt(kLightOn, t)); // obj->fLightPB->SetValue(kLightType, t, fLightPB->GetInt(kLightType, t)); obj->fLightPB->SetValue(kLightColor, t, fLightPB->GetInt(kLightOn, t)); obj->fLightPB->SetValue(kCastShadows, t, fLightPB->GetInt(kLightOn, t)); //obj->fLightPB->SetValue(kContrast, t, fLightPB->GetInt(kLightOn, t)); //obj->fLightPB->SetValue(kDiffSoft, t, fLightPB->GetInt(kLightOn, t)); //obj->fLightPB->SetValue(kDiffOn, t, fLightPB->GetInt(kLightOn, t)); obj->fLightPB->SetValue(kSpec, t, fLightPB->GetInt(kLightOn, t)); obj->fLightPB->SetValue(kSpecularColorSwatch, t, fLightPB->GetInt(kLightOn, t)); obj->fLightPB->SetValue(kIntensity, t, fLightPB->GetInt(kLightOn, t)); if( IHasAttenuation() ) { obj->fLightPB->SetValue(kUseAttenuationBool, t, fLightPB->GetInt(kLightType, t)); obj->fLightPB->SetValue(kAttenMaxFalloffEdit, t, fLightPB->GetInt(kLightOn, t)); obj->fLightPB->SetValue(kAttenTypeRadio, t, fLightPB->GetInt(kLightOn, t)); obj->fLightPB->SetValue(kShowConeBool, t, fLightPB->GetInt(kLightOn, t)); obj->fLightPB->SetValue(kHotSpot, t, fLightPB->GetInt(kLightOn, t)); obj->fLightPB->SetValue(kAttenMaxFalloffEdit, fLightPB->GetInt(kLightType, t)); obj->fLightPB->SetValue(kFallOff, t, fLightPB->GetInt(kLightOn, t)); obj->fLightPB->SetValue(kUseProjectorBool, t, fLightPB->GetInt(kLightOn, t)); obj->fLightPB->SetValue(kProjMapTexButton, t, fLightPB->GetInt(kLightOn, t)); } obj->ReplaceReference(kRefSpotLight,fLightPB->Clone(remap)); /* GeneralLight* newob = TRACKED_NEW GeneralLight(type); newob->enable = enable; newob->coneDisplay = coneDisplay; newob->useLight = useLight; newob->attenDisplay = attenDisplay; newob->useAtten = useAtten; newob->useAttenNear = useAttenNear; newob->attenNearDisplay = attenNearDisplay; newob->decayDisplay = decayDisplay; newob->shape = shape; newob->shadow = shadow; newob->shadowType = shadowType; newob->overshoot = overshoot; newob->projector = projector; newob->absMapBias = absMapBias; newob->exclList = exclList; newob->softenDiffuse = softenDiffuse; newob->affectDiffuse = affectDiffuse; newob->affectSpecular = affectSpecular; newob->ambientOnly = ambientOnly; newob->decayType = decayType; newob->atmosShadows = atmosShadows; newob->atmosOpacity = atmosOpacity; newob->atmosColAmt = atmosColAmt; newob->ReplaceReference(PBLOCK_REF,pblock->Clone(remap)); if (projMap) newob->ReplaceReference(PROJMAP_REF,projMap->Clone(remap)); if (shadProjMap) newob->ReplaceReference(SHADPROJMAP_REF,shadProjMap->Clone(remap)); if (shadType) newob->ReplaceReference(SHADTYPE_REF,shadType->Clone(remap)); if (emitter) newob->ReplaceReference(EMITTER_REF ,emitter->Clone(remap)); BaseClone(this, newob, remap); return(newob); */ //plRTLightBase *obj = (plRTLightBase*) fClassDesc->Create(false); //obj->ReplaceReference(kRefComp, fLightPB->Clone(remap)); return obj; } #endif void plRTLightBase::FreeCaches() { // fMesh.FreeAll(); } void plRTLightBase::BoxCircle(TimeValue t, float r, float d, Box3& box, int extraPt, Matrix3 *tm) { Point3 q[3*NUM_CIRC_PTS]; int npts; float asp; if ( 1 /*Circle Object*/) { npts = NUM_CIRC_PTS+extraPt; asp = -1.0f; } else { npts = 4+extraPt; asp = -1.0; } GetConePoints(t, asp , r, d, q); box.IncludePoints(q,npts,tm); } void plRTLightBase::BoxDirPoints(TimeValue t, float angle, float dist, Box3 &box, Matrix3 *tm) { int npts; Point3 q[3*NUM_CIRC_PTS]; npts = 1 /*Circle Object*/? GetCirXPoints(t,angle,dist,q): GetRectXPoints(t,angle,dist,q); box.IncludePoints(q,npts,tm); } void plRTLightBase::BoxPoints(TimeValue t, float angle, float dist, Box3 &box, Matrix3 *tm) { if (IsDir()) BoxCircle(t, angle, dist, box, 0,tm); else BoxDirPoints(t, angle, dist, box, tm); } void plRTLightBase::BoxLight(TimeValue t, INode *inode, Box3& box, Matrix3 *tm) { Point3 pt; float d; if (GetTargetPoint(t, inode, pt)) { Point3 loc = inode->GetObjectTM(t).GetTrans(); d = FLength(loc - pt) / FLength(inode->GetObjectTM(t).GetRow(2)); box += tm? (*tm)*Point3(0.0f, 0.0f, -d): Point3(0.0f, 0.0f, -d); } else { d = GetTDist(t); // if(fLightPB->GetInt(kLightType) == RT_FREE_DIR) // d = GetFallsize(t); if(IsSpot()) box += tm? (*tm)*Point3(0.0f, 0.0f, -d): Point3(0.0f, 0.0f, -d); if(IsDir()) { d = GetFallsize(t); box += tm? (*tm)*Point3(0.0f, 0.0f, -d): Point3(0.0f, 0.0f, -d); } } if( this->ClassID() == RTSPOT_LIGHT_CLASSID ) // if (fLightPB->GetInt(kLightType) == RT_FREE_SPOT || fLightPB->GetInt(kLightType) == RT_TARGET_SPOT) if((fLightPB->GetInt(kShowConeBool,t)) || (extDispFlags & EXT_DISP_ONLY_SELECTED)) { float rad = MaxF(GetHotspot(t), GetFallsize(t)); if (IsDir()) BoxCircle(t,rad,0.0f,box,1,tm); BoxCircle(t,rad,d,box,1,tm); } if( this->ClassID() == RTDIR_LIGHT_CLASSID || this->ClassID() == RTPDIR_LIGHT_CLASSID ) // if (fLightPB->GetInt(kLightType) == RT_FREE_DIR || fLightPB->GetInt(kLightType) == RT_TARGET_DIR) if((extDispFlags & EXT_DISP_ONLY_SELECTED)) { float rad = MaxF(GetHotspot(t), GetFallsize(t)); if (IsDir()) BoxCircle(t,rad,0.0f,box,1,tm); BoxCircle(t,rad,2.82841*GetFallsize(t),box,1,tm); //hack, hack. Do 2root2 at corners... } BOOL dispAtten = false; BOOL dispAttenNear = false; BOOL dispDecay = false; if( this->ClassID() == RTOMNI_LIGHT_CLASSID || this->ClassID() == RTSPOT_LIGHT_CLASSID ) { dispAtten = fLightPB->GetInt(kUseAttenuationBool,t); dispAttenNear = 0; //attenNearDisplay; dispDecay = (GetDecayType()&&(extDispFlags & EXT_DISP_ONLY_SELECTED)); } if( dispAtten || dispDecay) { if( this->ClassID() == RTOMNI_LIGHT_CLASSID ) { Point3 q[3*NUM_CIRC_PTS]; float rad = 0; if (dispAtten) rad = MaxF(GetAtten(t, ATTEN_START), GetAtten(t, ATTEN_END)); if (dispDecay) rad = MaxF(rad,0.0/*GetDecayRadius(t)*/); GetAttenPoints(t, rad, q); box.IncludePoints(q,3*NUM_CIRC_PTS,tm); } if( this->ClassID() == RTSPOT_LIGHT_CLASSID ) { if (dispAtten) { BoxPoints(t, GetFallsize(t), GetAtten(t,ATTEN_END), box, tm); BoxPoints(t, GetFallsize(t), GetAtten(t,ATTEN_START), box, tm); } if (dispDecay) BoxPoints(t, GetFallsize(t), 0.0/*GetDecayRadius(t)*/, box, tm); } } } int plRTLightBase::GetRectXPoints(TimeValue t, float angle, float dist, Point3 *q) { int i; if(dist==0.0f) dist = .00001f; float ang = DegToRad(angle)/2.0f; float da,sn,cs,x,y,z,a; float aspect = GetAspect(t); float w = dist * (float)tan(ang) * (float)sqrt((double)aspect); float h = w/aspect; float wang = (float)atan(w/dist); float hang = (float)atan(h/dist); float aw = float(atan(w/dist)*cos(hang)); // half-angle of top and bottom arcs float ah = float(atan(h/dist)*cos(wang)); // half-angle of left and right arcs int j = 0; // draw horizontal and vertical center lines da = wang/float(NUM_HALF_ARC); for(i = -NUM_HALF_ARC, a = -wang; i<= NUM_HALF_ARC; i++, a+=da) q[j++] = Point3(dist*(float)sin(a), 0.0f, -dist*(float)cos(a)); da = hang/float(NUM_HALF_ARC); for(i = -NUM_HALF_ARC, a = -hang; i<= NUM_HALF_ARC; i++, a+=da) q[j++] = Point3(0.0f, dist*(float)sin(a), -dist*(float)cos(a)); // draw top and bottom arcs da = aw/float(NUM_HALF_ARC); sn = (float)sin(hang); cs = (float)cos(hang); for (i = -NUM_HALF_ARC, a = -aw; i<= NUM_HALF_ARC; i++, a+=da) { x = dist*(float)sin(a); z = -dist*(float)cos(a); q[j] = Point3(x, z*sn, z*cs); q[j+NUM_ARC_PTS] = Point3(x,-z*sn, z*cs); j++; } j+= NUM_ARC_PTS; // draw left and right arcs da = ah/float(NUM_HALF_ARC); sn = (float)sin(wang); cs = (float)cos(wang); for (i = -NUM_HALF_ARC, a = -ah; i<= NUM_HALF_ARC; i++, a+=da) { y = dist*(float)sin(a); z = -dist*(float)cos(a); q[j] = Point3( z*sn, y, z*cs); q[j+NUM_ARC_PTS] = Point3(-z*sn, y, z*cs); j++; } return 6*NUM_ARC_PTS; } int plRTLightBase::GetCirXPoints(TimeValue t, float angle, float dist, Point3 *q) { int i; float ang = DegToRad(angle)/2.0f; float da = ang/float(NUM_HALF_ARC); // first draw circle: float d = dist*(float)cos(ang); GetConePoints(t, -1.0f, angle, d, q); int j=NUM_CIRC_PTS; // then draw Arc X float a = -ang; for(i = -NUM_HALF_ARC; i<= NUM_HALF_ARC; i++, a+=da) q[j++] = Point3(0.0f, dist*(float)sin(a), -dist*(float)cos(a)); a = -ang; for(i = -NUM_HALF_ARC; i<= NUM_HALF_ARC; i++, a+=da) q[j++] = Point3(dist*(float)sin(a), 0.0f, -dist*(float)cos(a)); return NUM_CIRC_PTS + 2*NUM_ARC_PTS; } void plRTLightBase::DrawX(TimeValue t, float asp, int npts, float dist, GraphicsWindow *gw, int indx) { Point3 q[3*NUM_CIRC_PTS+1]; Point3 u[2]; GetConePoints(t, asp, GetFallsize(t), dist, q); gw->polyline(npts, q,NULL, NULL, TRUE, NULL); u[0] = q[0]; u[1] = q[2*indx]; gw->polyline(2, u,NULL, NULL, FALSE, NULL); u[0] = q[indx]; u[1] = q[3*indx]; gw->polyline(2, u,NULL, NULL, FALSE, NULL); } void plRTLightBase::GetAttenPoints(TimeValue t, float rad, Point3 *q) { double a; float sn, cs; for(int i = 0; i < NUM_CIRC_PTS; i++) { a = (double)i * 2.0 * 3.1415926 / (double)NUM_CIRC_PTS; sn = rad * (float)sin(a); cs = rad * (float)cos(a); q[i+0*NUM_CIRC_PTS] = Point3(sn, cs, 0.0f); q[i+1*NUM_CIRC_PTS] = Point3(sn, 0.0f, cs); q[i+2*NUM_CIRC_PTS] = Point3(0.0f, sn, cs); } } // Draw warped rectangle void plRTLightBase::DrawWarpRect(TimeValue t, GraphicsWindow *gw, float angle, float dist, Point3 *q) { GetRectXPoints(t, angle,dist,q); for (int i=0; i<6; i++) gw->polyline(NUM_ARC_PTS, q+i*NUM_ARC_PTS,NULL, NULL, FALSE, NULL); } void plRTLightBase::DrawCircleX(TimeValue t, GraphicsWindow *gw, float angle, float dist, Point3 *q) { GetCirXPoints(t, angle,dist,q); gw->polyline(NUM_CIRC_PTS, q,NULL, NULL, TRUE, NULL); // circle gw->polyline(NUM_ARC_PTS, q+NUM_CIRC_PTS,NULL, NULL, FALSE, NULL); // vert arc gw->polyline(NUM_ARC_PTS, q+NUM_CIRC_PTS+NUM_ARC_PTS,NULL, NULL, FALSE, NULL); // horiz arc } void plRTLightBase::DrawSphereArcs(TimeValue t, GraphicsWindow *gw, float r, Point3 *q) { GetAttenPoints(t, r, q); gw->polyline(NUM_CIRC_PTS, q, NULL, NULL, TRUE, NULL); gw->polyline(NUM_CIRC_PTS, q+NUM_CIRC_PTS, NULL, NULL, TRUE, NULL); gw->polyline(NUM_CIRC_PTS, q+2*NUM_CIRC_PTS,NULL, NULL, TRUE, NULL); } // void plRTLightBase::DrawAttenCirOrRect(TimeValue t, GraphicsWindow *gw, float dist, BOOL froze, int uicol) { if (!froze) gw->setColor( LINE_COLOR, GetUIColor(uicol)); if (IsDir()) { int npts,indx; float asp; npts = NUM_CIRC_PTS; asp = -1.0f; indx = SEG_INDEX; DrawX(t, asp, npts, dist, gw, indx); } else { Point3 q[3*NUM_CIRC_PTS+1]; if( this->ClassID() == RTOMNI_LIGHT_CLASSID ) DrawSphereArcs(t, gw, dist, q); else DrawCircleX(t, gw, GetFallsize(t),dist,q); } } int plRTLightBase::DrawAtten(TimeValue t, INode *inode, GraphicsWindow *gw) { BOOL dispAtten = false; BOOL dispDecay = false; if( this->ClassID() == RTOMNI_LIGHT_CLASSID || this->ClassID() == RTSPOT_LIGHT_CLASSID ) { dispAtten = (fLightPB->GetInt(kUseAttenuationBool,t) && (extDispFlags & EXT_DISP_ONLY_SELECTED)); //BOOL dispAttenNear = (fLightPB->GetInt(kUseNearAtten) && (extDispFlags & EXT_DISP_ONLY_SELECTED))?TRUE:fLightPB->GetInt(kShowFarAttenRanges); dispDecay = (GetDecayType() && (extDispFlags & EXT_DISP_ONLY_SELECTED)); } if (dispAtten || dispDecay) { Matrix3 tm = inode->GetObjectTM(t); gw->setTransform(tm); BOOL froze = inode->IsFrozen() && !inode->Dependent(); if (dispAtten) { DrawAttenCirOrRect(t, gw, GetAtten(t,ATTEN_START), froze, COLOR_START_RANGE); DrawAttenCirOrRect(t, gw, GetAtten(t,ATTEN_END), froze, COLOR_END_RANGE); } if (dispDecay) { DrawAttenCirOrRect(t, gw, 0.0 /*DecayRadius() Stuff here */, froze, COLOR_DECAY_RADIUS); } } return 0; } void plRTLightBase::GetLocalBoundBox(TimeValue t, INode *node, ViewExp *vpt, Box3 &box) { //BuildMeshes(t); //box = fMesh.getBoundingBox(); // int nv; // Matrix3 tm; // GetMat(t, node,vpt,tm); // Point3 loc = tm.GetTrans(); // nv = fMesh.getNumVerts(); // box.Init(); // if(!(extDispFlags & EXT_DISP_ZOOM_EXT)) // box.IncludePoints(fMesh.verts,nv,&tm); // else // box += loc; // tm = node->GetObjectTM(t); // BoxLight(t, node, box, &tm); Point3 loc = node->GetObjectTM(t).GetTrans(); float scaleFactor = vpt->NonScalingObjectSize()*vpt->GetVPWorldWidth(loc) / 360.0f; box = fMesh.getBoundingBox(); box.Scale(scaleFactor); BoxLight(t, node, box, NULL); } /* RefTargetHandle Clone(RemapDir &remap = NoRemap()) { plRTLightBase* newOb = TRACKED_NEW plRTLightBase; newOb->fLightPB->SetValue(kLightOn, 0, this->fLightPB->GetInt(kLightOn, 0)); newOb->fLightPB->SetValue(kLightColor, 0, this->fLightPB->GetValue(kLightColor, 0)); newOb->fLightPB->SetValue(kLightExclude, 0, this->fLightPB->GetValue(kLightExclude, 0)); newOb->fLightPB->SetValue(kRed, 0, this->fLightPB->GetInt(kRed, 0)); newOb->fLightPB->SetValue(kGreen, 0, this->fLightPB->GetInt(kGreen, 0)); newOb->fLightPB->SetValue(kBlue, 0, this->fLightPB->GetInt(kBlue, 0)); newOb->fLightPB->SetValue(kHue, 0, this->fLightPB->GetInt(kHue, 0)); newOb->fLightPB->SetValue(kSat, 0, this->fLightPB->GetInt(kSat, 0)); newOb->fLightPB->SetValue(kVal, 0, this->fLightPB->GetInt(kVal, 0)); newOb->fLightPB->SetValue(kIntensity, 0, this->fLightPB->GetFloat(kIntensity, 0)); newOb->fLightPB->SetValue(kContrast, 0, this->fLightPB->GetFloat(kContrast, 0)); newOb->fLightPB->SetValue(kDiffSoft, 0, this->fLightPB->GetFloat(kDiffSoft, 0)); newOb->fLightPB->SetValue(kDiffOn, 0, this->fLightPB->GetInt(kDiffOn, 0)); newOb->fLightPB->SetValue(kStartAttenNear, 0, this->fLightPB->GetFloat(kStartAttenNear, 0)); newOb->fLightPB->SetValue(kAmbiOnly, 0, this->fLightPB->GetInt(kAmbiOnly, 0)); newOb->fLightPB->SetValue(kEndAttenNear, 0, this->fLightPB->GetFloat(kEndAttenNear, 0)); newOb->fLightPB->SetValue(kUseNearAtten, 0, this->fLightPB->GetInt(kUseNearAtten, 0)); newOb->fLightPB->SetValue(kShowNearAttenRanges, 0, this->fLightPB->GetInt(kShowNearAttenRanges, 0)); newOb->fLightPB->SetValue(kStartAttenFar, 0, this->fLightPB->GetFloat(kStartAttenFar, 0)); newOb->fLightPB->SetValue(kEndAttenFar, 0, this->fLightPB->GetFloat(kEndAttenFar, 0)); newOb->fLightPB->SetValue(kUseFarAtten, 0, this->fLightPB->GetInt(kUseFarAtten, 0)); newOb->fLightPB->SetValue(kShowFarAttenRanges, 0, this->fLightPB->GetInt(kShowFarAttenRanges, 0)); newOb->fLightPB->SetValue(kLightDecay, 0, this->fLightPB->GetInt(kLightDecay, 0)); newOb->fLightPB->SetValue(kRed, 0, this->fLightPB->GetInt(kRed, 0)); newOb->fLightPB->SetValue(kGreen, 0, this->fLightPB->GetInt(kGreen, 0)); newOb->fLightPB->SetValue(kBlue, 0, this->fLightPB->GetInt(kBlue, 0)); newOb->fLightPB->SetValue(kHue, 0, this->fLightPB->GetInt(kHue, 0)); newOb->fLightPB->SetValue(kSat, 0, this->fLightPB->GetInt(kSat, 0)); newOb->fLightPB->SetValue(kVal, 0, this->fLightPB->GetInt(kVal, 0)); newOb->fLightPB->SetValue(kIntensity, 0, this->fLightPB->GetFloat(kIntensity, 0)); newOb->fLightPB->SetValue(kContrast, 0, this->fLightPB->GetFloat(kContrast, 0)); newOb->fLightPB->SetValue(kDiffSoft, 0, this->fLightPB->GetFloat(kDiffSoft, 0)); newOb->fLightPB->SetValue(kDiffOn, 0, this->fLightPB->GetInt(kDiffOn, 0)); newOb->fLightPB->SetValue(kStartAttenNear, 0, this->fLightPB->GetFloat(kStartAttenNear, 0)); newOb->fLightPB->SetValue(kAmbiOnly, 0, this->fLightPB->GetInt(kAmbiOnly, 0)); newOb->fLightPB->SetValue(kEndAttenNear, 0, this->fLightPB->GetFloat(kEndAttenNear, 0)); newOb->fLightPB->SetValue(kUseNearAtten, 0, this->fLightPB->GetInt(kUseNearAtten, 0)); newOb->fLightPB->SetValue(kShowNearAttenRanges, 0, this->fLightPB->GetInt(kShowNearAttenRanges, 0)); newOb->fLightPB->SetValue(kStartAttenFar, 0, this->fLightPB->GetFloat(kStartAttenFar, 0)); newOb->fLightPB->SetValue(kEndAttenFar, 0, this->fLightPB->GetFloat(kEndAttenFar, 0)); */ /* kLightType, //Inserted in v1 kLightOn, //Inserted in v1 kLightColor, //Inserted in v1 kLightExclude, //Inserted in v1 kRed, //Inserted in v1 kGreen, //Inserted in v1 kBlue, //Inserted in v1 kHue, //Inserted in v1 kSat, //Inserted in v1 kVal, //Inserted in v1 kIntensity, //Inserted in v1 kContrast, //Inserted in v1 kDiffSoft, //Inserted in v1 kDiffOn, //Inserted in v1 kSpec, //Inserted in v1 kAmbiOnly, //Inserted in v1 kStartAttenNear, //Inserted in v1 kEndAttenNear, //Inserted in v1 kUseNearAtten, //Inserted in v1 kShowNearAttenRanges,//Inserted in v1 kStartAttenFar, //Inserted in v1 kEndAttenFar, //Inserted in v1 kUseFarAtten, //Inserted in v1 kShowFarAttenRanges, //Inserted in v1 kLightDecay, //Inserted in v1 kDecayEdit, //Inserted in v1 kShowDecay, //Inserted in v1 kUseProjectBool, //Inserted in v1 kProjMapTexButton, //Inserted in v1 kShowConeBool, //Inserted in v1 kOvershootBool, //Inserted in v1 kHotSpot, //Inserted in v1 kFallOff, //Inserted in v1 kLightShapeRadio, //Inserted in v1 kAspect, //Inserted in v1 kUseProjectorBool, //Inserted in v1 kProjMapTexButton2, //Inserted in v1 kTargetDist //Inserted in v1 GeneralLight* newob = TRACKED_NEW GeneralLight(type); newob->enable = enable; newob->coneDisplay = coneDisplay; newob->useLight = useLight; newob->attenDisplay = attenDisplay; newob->useAtten = useAtten; newob->useAttenNear = useAttenNear; newob->attenNearDisplay = attenNearDisplay; newob->decayDisplay = decayDisplay; newob->shape = shape; newob->shadow = shadow; newob->shadowType = shadowType; newob->overshoot = overshoot; newob->projector = projector; newob->absMapBias = absMapBias; newob->exclList = exclList; newob->softenDiffuse = softenDiffuse; newob->affectDiffuse = affectDiffuse; newob->affectSpecular = affectSpecular; newob->ambientOnly = ambientOnly; newob->decayType = decayType; newob->atmosShadows = atmosShadows; newob->atmosOpacity = atmosOpacity; newob->atmosColAmt = atmosColAmt; newob->ReplaceReference(PBLOCK_REF,pblock->Clone(remap)); if (projMap) newob->ReplaceReference(PROJMAP_REF,projMap->Clone(remap)); if (shadProjMap) newob->ReplaceReference(SHADPROJMAP_REF,shadProjMap->Clone(remap)); if (shadType) newob->ReplaceReference(SHADTYPE_REF,shadType->Clone(remap)); if (emitter) newob->ReplaceReference(EMITTER_REF ,emitter->Clone(remap)); BaseClone(this, newob, remap); return(newob); } */ //} void plRTLightBase::GetWorldBoundBox(TimeValue t, INode *node, ViewExp *vpt, Box3 &box) { GetLocalBoundBox( t, node, vpt, box ); box = box * node->GetObjectTM( t ); } void plRTLightBase::GetDeformBBox(TimeValue t, Box3& box, Matrix3 *tm, BOOL useSel ) { box = fMesh.getBoundingBox(tm); } int plRTLightBase::Display(TimeValue t, INode *node, ViewExp *vpt, int flags) { Matrix3 m; // if (!enable) // return 0; GraphicsWindow *gw = vpt->getGW(); GetMat(t,node,vpt,m); gw->setTransform(m); DWORD rlim = gw->getRndLimits(); gw->setRndLimits(GW_WIREFRAME|GW_BACKCULL|(gw->getRndMode() & GW_Z_BUFFER)); if (node->Selected()) gw->setColor( LINE_COLOR, GetSelColor()); else if(!node->IsFrozen() && !node->Dependent()) { if(fLightPB->GetInt(kLightOn)) gw->setColor( LINE_COLOR, GetUIColor(COLOR_LIGHT_OBJ)); // I un-commented this line DS 6/11/99 else gw->setColor( LINE_COLOR, 0.0f, 0.0f, 0.0f); } fMesh.render( gw, gw->getMaterial(), (flags&USE_DAMAGE_RECT) ? &vpt->GetDammageRect() : NULL, COMP_ALL); DrawConeAndLine(t, node, gw, 1); // DrawAtten(t, node, gw); gw->setRndLimits(rlim); return 0; } static void RemoveScaling(Matrix3 &tm) { AffineParts ap; decomp_affine(tm, &ap); tm.IdentityMatrix(); tm.SetRotate(ap.q); tm.SetTrans(ap.t); } void plRTLightBase::GetMat(TimeValue t, INode* inode, ViewExp *vpt, Matrix3& tm) { tm = inode->GetObjectTM(t); // tm.NoScale(); RemoveScaling(tm); float scaleFactor = vpt->NonScalingObjectSize()*vpt->GetVPWorldWidth(tm.GetTrans())/(float)360.0; tm.Scale(Point3(scaleFactor,scaleFactor,scaleFactor)); } void plRTLightBase::GetConePoints(TimeValue t, float aspect, float angle, float dist, Point3 *q) { float ta = (float)tan(0.5*DegToRad(angle)); if(1 /*fLightPB->GetFloat(kAspect, t) <= 0.0f*/) { // CIRCULAR float rad = dist * ta; double a; if(IsDir()) rad = angle; int i; for(i = 0; i < NUM_CIRC_PTS; i++) { a = (double)i * 2.0 * 3.1415926 / (double)NUM_CIRC_PTS; q[i] = Point3(rad*(float)sin(a), rad*(float)cos(a), -dist); } q[i] = q[0] + Point3(0.0f, 15.0f, 0.0f); } else { // RECTANGULAR float w = IsDir()? angle : dist * ta * (float)sqrt((double)aspect); float h = w / aspect; q[0] = Point3( w, h,-dist); q[1] = Point3(-w, h,-dist); q[2] = Point3(-w,-h,-dist); q[3] = Point3( w,-h,-dist); q[4] = Point3( 0.0f, h+15.0f, -dist); q[5] = Point3( 0.0f, h, -dist); } } #define HOTCONE 0 #define FALLCONE 1 void plRTLightBase::DrawCone(TimeValue t, GraphicsWindow *gw, float dist) { Point3 q[NUM_CIRC_PTS+1], u[3]; int dirLight = IsDir(); int i; BOOL dispAtten = false; BOOL dispDecay = false; if( this->ClassID() == RTOMNI_LIGHT_CLASSID || this->ClassID() == RTSPOT_LIGHT_CLASSID ) { dispAtten = (fLightPB->GetInt(kUseAttenuationBool, t) && (extDispFlags & EXT_DISP_ONLY_SELECTED));//attenDisplay; dispDecay = (/*fLightPB->GetInt(kAttenTypeRadio, t)*/GetDecayType() && (extDispFlags & EXT_DISP_ONLY_SELECTED)); } if(!IsDir()) GetConePoints(t, -1.0f, GetHotspot(t), dist, q); else GetConePoints(t, -1.0f, 20.0, dist, q); gw->setColor( LINE_COLOR, GetUIColor(COLOR_HOTSPOT)); if(1 /*Circular Hack*/) { // CIRCULAR if(GetHotspot(t) >= GetFallsize(t)) { // draw (far) hotspot circle u[0] = q[0]; u[1] = q[NUM_CIRC_PTS]; gw->polyline( 2, u, NULL, NULL, FALSE, NULL); } gw->polyline(NUM_CIRC_PTS, q, NULL, NULL, TRUE, NULL); if (dirLight) { // draw 4 axial hotspot lines for (i = 0; i < NUM_CIRC_PTS; i += SEG_INDEX) { u[0] = q[i]; u[1] = q[i]; u[1].z += dist; gw->polyline( 2, u, NULL, NULL, FALSE, NULL ); } GetConePoints(t, -1.0f, 20/*GetHotspot(t)*/, 0.0f, q); // draw (near) hotspot circle gw->polyline(NUM_CIRC_PTS, q, NULL, NULL, TRUE, NULL); } else { // draw 4 axial lines u[0] = Point3(0,0,0); for (i = 0; i < NUM_CIRC_PTS; i += SEG_INDEX) { u[1] = q[i]; gw->polyline( 2, u, NULL, NULL, FALSE, NULL ); } } if(!IsDir()) GetConePoints(t, -1.0f, GetFallsize(t), dist, q); else GetConePoints(t, -1.0f, 200.0, dist, q); gw->setColor( LINE_COLOR, GetUIColor(COLOR_FALLOFF)); if(GetHotspot(t) < GetFallsize(t)) { // draw (far) fallsize circle u[0] = q[0]; u[1] = q[NUM_CIRC_PTS]; gw->polyline( 2, u, NULL, NULL, FALSE, NULL); u[0] = Point3(0,0,0); } gw->polyline(NUM_CIRC_PTS, q, NULL, NULL, TRUE, NULL); if (dirLight) { float dfar = q[0].z; float dnear = 0.0f; if (dispAtten) { dfar = MinF(-GetAtten(t,ATTEN_END),dfar); /// dnear = MaxF(-GetAtten(t,ATTEN_START),dnear); } if (dispDecay) { dfar = MinF(/*-GetDecayRadius(t)*/ 0.0,dfar); } // draw axial fallsize lines for (i = 0; i < NUM_CIRC_PTS; i += SEG_INDEX) { u[0] = q[i]; u[0].z = dfar; u[1] = q[i]; u[1].z = dnear; gw->polyline( 2, u, NULL, NULL, FALSE, NULL ); } GetConePoints(t, -1.0f, 10000.0, 0.0f, q); // draw (near) fallsize circle gw->polyline(NUM_CIRC_PTS, q, NULL, NULL, TRUE, NULL); } else { float cs = (float)cos(DegToRad(GetFallsize(t)*0.5f)); float dfar = q[0].z; if (dispAtten) dfar = MinF(-cs*GetAtten(t,ATTEN_END),dfar); if (dispDecay) dfar = MinF(/*-cs*GetDecayRadius(t)*/0.0,dfar); for (i = 0; i < NUM_CIRC_PTS; i += SEG_INDEX) { u[1] = -q[i]*dfar/dist; gw->polyline( 2, u, NULL, NULL, FALSE, NULL ); } } } } int plRTLightBase::DrawConeAndLine(TimeValue t, INode* inode, GraphicsWindow *gw, int drawing ) { if(!IsSpot() && !IsDir()) return 0; Matrix3 tm = inode->GetObjectTM(t); gw->setTransform(tm); gw->clearHitCode(); if( 0 ) { Point3 pt,v[3]; if (GetTargetPoint(t, inode, pt)) { float den = FLength(tm.GetRow(2)); float dist = (den!=0) ? FLength(tm.GetTrans()-pt) / den : 0.0f; fLightPB->SetValue(kAttenMaxFalloffEdit, t, dist); //fLightPB->SetValue(kTargetDist, t, dist); //if (hSpotLight&&(currentEditLight==this)) { // TCHAR buf[40]; // _stprintf(buf,_T("%0.3f"),targDist); // SetWindowText(GetDlgItem(hSpotLight,IDC_TARG_DISTANCE),buf); // } if ((drawing != -1) && (fLightPB->GetInt(kShowConeBool, t) || (extDispFlags & EXT_DISP_ONLY_SELECTED))) DrawCone(t, gw, dist); if(!inode->IsFrozen() && !inode->Dependent()) gw->setColor( LINE_COLOR, GetUIColor(COLOR_TARGET_LINE)); v[0] = Point3(0,0,0); v[1] = Point3(0.0f, 0.0f, (drawing == -1)? (-0.9f * dist): -dist); gw->polyline( 2, v, NULL, NULL, FALSE, NULL ); } } else if( this->ClassID() == RTSPOT_LIGHT_CLASSID ) { if ((drawing != -1) && (fLightPB->GetInt(kShowConeBool, t) || (extDispFlags & EXT_DISP_ONLY_SELECTED))) DrawCone(t, gw, fLightPB->GetFloat( kAttenMaxFalloffEdit, t ) ); } else if( this->ClassID() == RTDIR_LIGHT_CLASSID ) { if ((extDispFlags & EXT_DISP_ONLY_SELECTED)) DrawCone(t, gw, 500/*GetTDist(t)*/); } return gw->checkHitCode(); } //// DrawArrow /////////////////////////////////////////////////////////////// void plRTLightBase::DrawArrow( TimeValue t, GraphicsWindow *gw, Point3 &direction, float dist ) { Point3 pts[ 5 ]; pts[ 0 ] = Point3( 0, 0, 0 ); pts[ 1 ] = direction * dist; pts[ 3 ] = pts[ 1 ] - direction * 10.f; pts[ 2 ] = pts[ 3 ] + Point3( direction.y, direction.z, direction.x ) * 5.f; gw->polyline( 4, pts, nil, nil, true, nil ); } int plRTLightBase::HitTest(TimeValue t, INode *node, int type, int crossing, int flags, IPoint2 *p, ViewExp *vpt) { DWORD savedLimits; GraphicsWindow *gw = vpt->getGW(); HitRegion hitRegion; int res; Matrix3 m; MakeHitRegion(hitRegion, type, crossing, 4, p); Material *mtl = gw->getMaterial(); gw->setRndLimits( ((savedLimits = gw->getRndLimits()) | GW_PICK) & ~(GW_ILLUM|GW_BACKCULL)); GetMat(t,node,vpt,m); //BuildMeshes(t); gw->setTransform(m); res = fMesh.select( gw, mtl, &hitRegion, flags & HIT_ABORTONHIT); // if not, check the target line, and set the pair flag if it's hit if( !res ) { // this special case only works with point selection of targeted lights if((type != HITTYPE_POINT) || !node->GetTarget()) return 0; // don't let line be active if only looking at selected stuff and target isn't selected if((flags & HIT_SELONLY) && !node->GetTarget()->Selected() ) return 0; gw->clearHitCode(); if(res = DrawConeAndLine(t, node, gw, -1)) node->SetTargetNodePair(1); } gw->setRndLimits(savedLimits); return res; //return fMesh.select(gw,node->Mtls(),&hitRegion,flags & HIT_ABORTONHIT,node->NumMtls()); } static void GenericSnap(TimeValue t, INode* inode, SnapInfo *snap, IPoint2 *p, ViewExp *vpt) { // Make sure the vertex priority is active and at least as important as the best snap so far if(snap->vertPriority > 0 && snap->vertPriority <= snap->priority) { Matrix3 tm = inode->GetObjectTM(t); GraphicsWindow *gw = vpt->getGW(); gw->setTransform(tm); Point2 fp = Point2((float)p->x, (float)p->y); IPoint3 screen3; Point2 screen2; Point3 vert(0.0f,0.0f,0.0f); gw->wTransPoint(&vert,&screen3); screen2.x = (float)screen3.x; screen2.y = (float)screen3.y; // Are we within the snap radius? int len = (int)Length(screen2 - fp); if(len <= snap->strength) { // Is this priority better than the best so far? if(snap->vertPriority < snap->priority) { snap->priority = snap->vertPriority; snap->bestWorld = vert * tm; snap->bestScreen = screen2; snap->bestDist = len; } // Closer than the best of this priority? else if(len < snap->bestDist) { snap->priority = snap->vertPriority; snap->bestWorld = vert * tm; snap->bestScreen = screen2; snap->bestDist = len; } } } } void plRTLightBase::Snap(TimeValue t, INode* inode, SnapInfo *snap, IPoint2 *p, ViewExp *vpt) { GenericSnap(t,inode,snap,p,vpt); } // This generic snap routine is used to snap to the 0,0,0 point of the given node. For lights, // this works to snap all types. RefTargetHandle plRTLightBase::GetReference(int i) { /* kRefProjMap, kRefShadowProjMap, kRefShadowType, *///Texmap* MyMap; switch(i) { case kRefGeneralLightProp: return NULL; case kRefProjMap: //if(fLightPB->GetTexmap(kProjMapTexButton, 0) != NULL) //{ // MyMap = fLightPB->GetTexmap(kProjMapTexButton, 0); //return (RefTargetHandle) MyMap; //}else return NULL; case kRefShadowProjMap: return NULL; case kRefShadowType: return NULL; case kRefOmniLight: case kRefSpotLight: case kRefTSpotLight: case kRefDirLight: case kRefTDirLight: case kRefProjDirLight: return (RefTargetHandle)fLightPB; default: return NULL; } } void plRTLightBase::SetReference(int ref, RefTargetHandle rtarg) { //Texmap* MyMap; switch(ref) { case kRefGeneralLightProp: return; case kRefProjMap: //MyMap = (Texmap *)rtarg; //fLightPB->SetValue(kProjMapTexButton, 0, MyMap); //if (projMapName) // projMapName->SetText(projMap?projMap->GetFullName().data():GetString(IDS_DB_NONE)); return; case kRefShadowProjMap: return; case kRefShadowType: return; case kRefOmniLight: case kRefSpotLight: case kRefTSpotLight: case kRefDirLight: case kRefTDirLight: case kRefProjDirLight: fLightPB = (IParamBlock2*)rtarg; break; } //fLightPB = (IParamBlock2*)rtarg; } RefResult plRTLightBase::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message) { if( fLightPB ) { ParamID param = fLightPB->LastNotifyParamID(); if( param == kAmbientOnlyStub ) { fLightPB->EnableNotifications( false ); fLightPB->SetValue( kAmbientOnlyStub, TimeValue( 0 ), false ); // Assume this was true, since, well, we're IN NotifyRefChanged.... fLightPB->EnableNotifications( true ); return REF_SUCCEED; } } return REF_SUCCEED; } void plRTLightBase::BeginEditParams(IObjParam *ip, ULONG flags, Animatable *prev) { fIP = ip; fClassDesc->BeginEditParams(ip, this, flags, prev); } void plRTLightBase::EndEditParams(IObjParam *ip, ULONG flags, Animatable *next) { GenLight::EndEditParams( ip, flags, next ); fIP = NULL; fClassDesc->EndEditParams(ip, this, flags, next); } RefResult plRTLightBase::EvalLightState(TimeValue t, Interval& valid, LightState *ls) { //t uselight; //#if 0 //fLightPB->GetInt(kLightOn, t); if(fLightPB->GetInt(kLightOn, t) == true) ls->color = GetRGBColor(t,valid); else ls->color = Color(0,0,0); ls->on = fLightPB->GetInt(kLightOn, t); ls->intens = GetIntensity(t, valid); if( this->ClassID() == RTSPOT_LIGHT_CLASSID || this->ClassID() == RTOMNI_LIGHT_CLASSID ) { ls->hotsize = GetHotspot(t, valid); ls->fallsize = GetFallsize(t, valid); ls->useNearAtten = GetUseAttenNear(); ls->useAtten = GetUseAtten(); ls->attenStart = GetAtten(t, ATTEN_START, valid); ls->attenEnd = GetAtten(t, ATTEN_END, valid); }else { ls->hotsize = 20; ls->fallsize = 10000; ls->useNearAtten = false; //GetUseAttenNear(); ls->useAtten = false; //GetUseAtten(); //ls->attenStart = GetAtten(t, ATTEN_START, valid); //ls->attenEnd = GetAtten(t, ATTEN_END, valid); } ls->shape = GW_SHAPE_CIRCULAR; //fLightPB->GetInt(kLightShapeRadio); ls->aspect = -1.0;//GetAspect(t, valid); ls->overshoot = false; //GetOvershoot(); ls->shadow = GetShadow(); ls->ambientOnly = false; //fLightPB->GetValue( kAmbiOnly,t, ls->ambientOnly, valid); //ls->ambientOnly = fLightP.AmbiOnly; ls->affectDiffuse = true; //fLightPB->GetInt(kDiffOn,t); //ls->affectDiffusey = fLightP.AmbiOnly; ls->affectSpecular = fLightPB->GetInt(kSpec,t); //ls- = fLightP.DiffOn;; //ls-> if( this->ClassID() == RTOMNI_LIGHT_CLASSID ) ls->type = OMNI_LGT; else if( this->ClassID() == RTDIR_LIGHT_CLASSID || this->ClassID() == RTPDIR_LIGHT_CLASSID ) ls->type = DIRECT_LGT; else ls->type = SPOT_LGT; return REF_SUCCEED; } #if 0 #define PLASMAOBJ_DATA_CHUNK 1 IOResult plRTLightBase::Save(ISave* isave) { return IO_OK; } IOResult plRTLightBase::Load(ILoad* iload) { ULONG nb; IOResult res; int numrefs = 0; while (IO_OK == (res = iload->OpenChunk())) { if (iload->CurChunkID() == PLASMAOBJ_DATA_CHUNK) res = iload->Read(&numrefs, sizeof(int), &nb); iload->CloseChunk(); if (res != IO_OK) return res; } return IO_OK; } #endif ObjLightDesc *plRTLightBase::CreateLightDesc(INode *n, BOOL forceShadowBuf) { return NULL; } void plRTLightBase::SetHotspot(TimeValue t, float f) { if(!IsSpot()) return; if(f < 0.5f) f = 0.5f; if(!IsDir() && (f > 179.5f)) f = 179.5f; //pblock->SetValue( PB_HOTSIZE, t, f ); fLightPB->SetValue(kHotSpot, t, f); //fLightP.HotSpot = f; NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE); } float plRTLightBase::GetHotspot(TimeValue t, Interval& valid) { Interval iv; if(!IsSpot() && !IsDir()) return -1.0f; float f; //pblock->GetValue( PB_HOTSIZE, t, f, valid ); if(IsSpot()) fLightPB->GetValue(kHotSpot, t, f, FOREVER); else f = 20.0; if(GetFallsize(t, iv) < f ) return GetFallsize(t, iv) - 2.0; return f; } void plRTLightBase::SetRGBColor(TimeValue t, Point3& rgb) { //fLightPB->SetValue(plRTLightBase::kRed, t, rgb.x); //fLightPB->SetValue(plRTLightBase::kGreen, t, rgb.y); //fLightPB->SetValue(plRTLightBase::kBlue, t, rgb.z); fLightPB->SetValue(kLightColor, t, rgb ); NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE); } Point3 plRTLightBase::GetRGBColor(TimeValue t, Interval &valid) { //Point3 Foo = Point3(fLightPB->GetInt(plRTLightBase::kRed, t), fLightPB->GetInt(plRTLightBase::kGreen, t), fLightPB->GetInt(plRTLightBase::kBlue, t)); Point3 rgb; fLightPB->GetValue( kLightColor, t, rgb, valid ); return rgb; } void plRTLightBase::SetFallsize(TimeValue t, float f) { if(!IsSpot() ) return; if(f < 0.5f) f = 0.5f; if(!IsDir() && (f > 179.5f)) f = 179.5f; //pblock->SetValue( PB_FALLSIZE, t, f ); fLightPB->SetValue(kFallOff, t, f); NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE); } float plRTLightBase::GetFallsize(TimeValue t, Interval& valid) { if(!IsSpot() && !IsDir()) return -1.0f; float f; //pblock->GetValue( PB_FALLSIZE, t, f, valid ); if(IsSpot()) fLightPB->GetValue(kFallOff, t, f, valid); else f = 200.0; return f; } void plRTLightBase::SetAtten(TimeValue t, int which, float f) { if(which != ATTEN_START) fLightPB->SetValue(kAttenMaxFalloffEdit, t, f); NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE); } float plRTLightBase::GetAtten(TimeValue t, int which, Interval& valid) { float f = 0.0; //if(fLightPB->GetInt(kEndAttenFar, t) == 1) //if(LyteType == RT_OMNI) // fLightPB->GetValue(kStartAttenFar, t, f, FOREVER); //else // fLightPB->GetValue(kStartAttenNear, t, f, FOREVER); if(which == LIGHT_ATTEN_START) return f; else return( fLightPB->GetFloat(kAttenMaxFalloffEdit, t)); //return f; } void plRTLightBase::SetTDist(TimeValue t, float f) { // int i; // fLightPB->GetInt(kLightType, t, i); //pblock->SetValue( PB_TDIST, t, f ); //To be implemented. if( IHasAttenuation() ) fLightPB->SetValue(kAttenMaxFalloffEdit, t, f); //fLightPB->SetValue(kTargetDist, t, f); NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE); } float plRTLightBase::GetTDist(TimeValue t, Interval& valid) { if(!IsSpot()) return -1.0f; // int i; //fLightPB->GetValue(kLightType, t, i, valid); float f = -1.0; fLightPB->GetFloat( kAttenMaxFalloffEdit, t ); //pblock->GetValue( PB_TDIST, t, f, valid ); //fLightPB->GetValue(kTargetDist, t, f, valid); return f; } void plRTLightBase::SetConeDisplay(int s, int notify) { if(!IsDir()) fLightPB->SetValue(kShowConeBool, 0, s); if(notify && IsSpot()) NotifyDependents(FOREVER, PART_OBJ, REFMSG_CHANGE); } BOOL plRTLightBase::GetConeDisplay(void) { if(!IsDir()) return fLightPB->GetInt(kShowConeBool); return false; } void plRTLightBase::SetProjMap(BitmapInfo* pmap) { //plLayerTex* MyMap = TRACKED_NEW plLayerTex; if(!fTex) fTex = TRACKED_NEW plLayerTex; fTex->SetBitmap(pmap); ReplaceReference(kRefProjMap,fTex); IParamBlock2 *bitmapPB = fTex->GetParamBlockByID(plLayerTex::kBlkBitmap); bitmapPB->SetValue(kBmpUseBitmap, 0, 1); // This is set in the call to fTex->SetBitmap(pmap) //PBBitmap pbb(*pmap); //bitmapPB->SetValue(kBmpBitmap, 0, &pbb); //Texmap* MyMap; //fLightPB->GetValue(kProjMapTexButton, 0, MyMap, FOREVER); if (fTex) fLightPB->SetValue(kUseProjectorBool, 0, true); NotifyDependents(FOREVER,0,REFMSG_SUBANIM_STRUCTURE_CHANGED); if( fLightPB->GetMap() ) { fLightPB->GetMap()->Invalidate(kProjMapTexButton); fLightPB->GetMap()->Invalidate(kUseProjectorBool); } } BOOL plRTLightBase::GetShadow() { return fLightPB->GetInt(kCastShadows); } void plRTLightBase::SetShadow(int a) { fLightPB->SetValue(kCastShadows, 0, 1); } Texmap* plRTLightBase::GetProjMap() { if( !fLightPB->GetInt(kUseProjectorBool) ) return NULL; if( GetTex() ) { const char* dbgTexName = GetTex()->GetName(); IParamBlock2 *bitmapPB = fTex->GetParamBlockByID(plLayerTex::kBlkBitmap); hsAssert(bitmapPB, "LayerTex with no param block"); int noCompress = fLightPB->GetInt(kProjNoCompress); int noMip = fLightPB->GetInt(kProjNoMip); bitmapPB->SetValue(kBmpNonCompressed, TimeValue(0), noCompress); bitmapPB->SetValue(kBmpNoFilter, TimeValue(0), noMip); } return (Texmap*) GetTex(); } void plRTLightBase::UpdateTargDistance(TimeValue t, INode* inode) { if( this->ClassID() == RTSPOT_LIGHT_CLASSID ) { Point3 pt,v[3]; if (GetTargetPoint(t, inode, pt)) { Matrix3 tm = inode->GetObjectTM(t); float den = FLength(tm.GetRow(2)); float dist = (den!=0) ? FLength(tm.GetTrans()-pt) / den : 0.0f; fLightPB->SetValue(kAttenMaxFalloffEdit, t, dist); // fLightPB->SetValue(kTargetDist, t, dist); //TCHAR buf[40]; //_stprintf(buf,_T("%0.3f"),targDist); //SetWindowText(GetDlgItem(hSpotLight,IDC_TARG_DISTANCE),buf); } } } /// // // // Target Creation for Targeted Lights... // // // #if 0 class TSpotCreationManager : public MouseCallBack, ReferenceMaker { private: CreateMouseCallBack *createCB; INode *lgtNode,*targNode; plRTLightBase *lgtObject; TargetObject *targObject; int attachedToNode; IObjCreate *createInterface; ClassDesc *cDesc; Matrix3 mat; // the nodes TM relative to the CP IPoint2 pt0; int ignoreSelectionChange; int lastPutCount; void CreateNewObject(); int NumRefs() { return 1; } RefTargetHandle GetReference(int i) { return (RefTargetHandle)lgtNode; } void SetReference(int i, RefTargetHandle rtarg) { lgtNode = (INode *)rtarg; } // StdNotifyRefChanged calls this, which can change the partID to new value // If it doesnt depend on the particular message& partID, it should return // REF_DONTCARE RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message); public: void Begin( IObjCreate *ioc, ClassDesc *desc ); void End(); TSpotCreationManager() { ignoreSelectionChange = FALSE; } int proc( HWND hwnd, int msg, int point, int flag, IPoint2 m ); BOOL SupportAutoGrid(){return TRUE;} }; #define CID_TSPOTCREATE CID_USER + 3 class TSpotCreateMode : public CommandMode { TSpotCreationManager proc; public: void Begin( IObjCreate *ioc, ClassDesc *desc ) { proc.Begin( ioc, desc ); } void End() { proc.End(); } int Class() { return CREATE_COMMAND; } int ID() { return CID_TSPOTCREATE; } MouseCallBack *MouseProc(int *numPoints) { *numPoints = 1000000; return &proc; } ChangeForegroundCallback *ChangeFGProc() { return CHANGE_FG_SELECTED; } BOOL ChangeFG( CommandMode *oldMode ) { return (oldMode->ChangeFGProc() != CHANGE_FG_SELECTED); } void EnterMode() { } void ExitMode() { } BOOL IsSticky() { return FALSE; } }; static TSpotCreateMode theTSpotCreateMode; #endif #if 0 void TSpotCreationManager::Begin( IObjCreate *ioc, ClassDesc *desc ) { createInterface = ioc; cDesc = desc; attachedToNode = FALSE; createCB = NULL; lgtNode = NULL; targNode = NULL; lgtObject = NULL; targObject = NULL; CreateNewObject(); } void TSpotCreationManager::End() { if ( lgtObject ) { lgtObject->EndEditParams( (IObjParam*)createInterface, END_EDIT_REMOVEUI, NULL); if ( !attachedToNode ) { // RB 4-9-96: Normally the hold isn't holding when this // happens, but it can be in certain situations (like a track view paste) // Things get confused if it ends up with undo... theHold.Suspend(); //delete lgtObject; lgtObject->DeleteThis(); // JBW 11.1.99, this allows scripted plugin lights to delete cleanly lgtObject = NULL; theHold.Resume(); // RB 7/28/97: If something has been put on the undo stack since this object was created, we have to flush the undo stack. if (theHold.GetGlobalPutCount()!=lastPutCount) { GetSystemSetting(SYSSET_CLEAR_UNDO); } macroRec->Cancel(); // JBW 4/23/99 } else if ( lgtNode ) { // Get rid of the reference. DeleteReference(0); // sets lgtNode = NULL } } } RefResult TSpotCreationManager::NotifyRefChanged( Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message) { switch (message) { case REFMSG_PRENOTIFY_PASTE: case REFMSG_TARGET_SELECTIONCHANGE: if ( ignoreSelectionChange ) { break; } if (lgtObject && lgtNode==hTarget) { // this will set camNode== NULL; DeleteReference(0); goto endEdit; } // fall through case REFMSG_TARGET_DELETED: if ( lgtObject && lgtNode==hTarget ) { endEdit: lgtObject->EndEditParams( (IObjParam*)createInterface, 0, NULL); lgtObject = NULL; lgtNode = NULL; CreateNewObject(); attachedToNode = FALSE; } else if (targNode==hTarget) { targNode = NULL; targObject = NULL; } break; } return REF_SUCCEED; } void TSpotCreationManager::CreateNewObject() { lgtObject = (plRTLightBase *)cDesc->Create(); lastPutCount = theHold.GetGlobalPutCount(); macroRec->BeginCreate(cDesc); // JBW 4/23/99 // Start the edit params process if ( lgtObject ) { lgtObject->BeginEditParams( (IObjParam*)createInterface, BEGIN_EDIT_CREATE, NULL ); } } static void whoa(){}; static BOOL needToss; int TSpotCreationManager::proc( HWND hwnd, int msg, int point, int flag, IPoint2 m ) { int res; TSTR targName; ViewExp *vpx = createInterface->GetViewport(hwnd); assert( vpx ); switch ( msg ) { case MOUSE_POINT: switch ( point ) { case 0: pt0 = m; assert( lgtObject ); vpx->CommitImplicitGrid(m, flag); //KENNY MERGE if ( createInterface->SetActiveViewport(hwnd) ) { return FALSE; } if (createInterface->IsCPEdgeOnInView()) { res = FALSE; goto done; } // if lights were hidden by category, re-display them GetCOREInterface()->SetHideByCategoryFlags( GetCOREInterface()->GetHideByCategoryFlags() & ~HIDE_LIGHTS); if ( attachedToNode ) { // send this one on its way lgtObject->EndEditParams( (IObjParam*)createInterface, 0, NULL); macroRec->EmitScript(); // JBW 4/23/99 // Get rid of the reference. if (lgtNode) DeleteReference(0); // new object CreateNewObject(); // creates lgtObject } needToss = theHold.GetGlobalPutCount()!=lastPutCount; theHold.Begin(); // begin hold for undo mat.IdentityMatrix(); // link it up lgtNode = createInterface->CreateObjectNode( lgtObject); attachedToNode = TRUE; assert( lgtNode ); createCB = lgtObject->GetCreateMouseCallBack(); createInterface->SelectNode( lgtNode ); // Create target object and node targObject = TRACKED_NEW TargetObject; assert(targObject); targNode = createInterface->CreateObjectNode( targObject); assert(targNode); targName = lgtNode->GetName(); targName += GetString(IDS_DB_DOT_TARGET); targNode->SetName(targName); // hook up camera to target using lookat controller. createInterface->BindToTarget(lgtNode,targNode); // Reference the new node so we'll get notifications. MakeRefByID( FOREVER, 0, lgtNode); // Position camera and target at first point then drag. mat.IdentityMatrix(); //mat[3] = vpx->GetPointOnCP(m); #ifdef _3D_CREATE mat.SetTrans( vpx->SnapPoint(m,m,NULL,SNAP_IN_3D) ); #else mat.SetTrans(vpx->SnapPoint(m,m,NULL,SNAP_IN_PLANE)); #endif createInterface->SetNodeTMRelConstPlane(lgtNode, mat); createInterface->SetNodeTMRelConstPlane(targNode, mat); lgtObject->Enable(1); ignoreSelectionChange = TRUE; createInterface->SelectNode( targNode,0); ignoreSelectionChange = FALSE; res = TRUE; break; case 1: if (Length(m-pt0)<2) goto abort; //mat[3] = vpx->GetPointOnCP(m); #ifdef _3D_CREATE mat.SetTrans( vpx->SnapPoint(m,m,NULL,SNAP_IN_3D) ); #else mat.SetTrans(vpx->SnapPoint(m,m,NULL,SNAP_IN_PLANE)); #endif macroRec->Disable(); // JBW 4/23/99 createInterface->SetNodeTMRelConstPlane(targNode, mat); macroRec->Enable(); ignoreSelectionChange = TRUE; createInterface->SelectNode( lgtNode); ignoreSelectionChange = FALSE; theHold.Accept(IDS_DS_CREATE); createInterface->AddLightToScene(lgtNode); createInterface->RedrawViews(createInterface->GetTime()); res = FALSE; // We're done break; } break; case MOUSE_MOVE: //mat[3] = vpx->GetPointOnCP(m); #ifdef _3D_CREATE mat.SetTrans( vpx->SnapPoint(m,m,NULL,SNAP_IN_3D) ); #else mat.SetTrans(vpx->SnapPoint(m,m,NULL,SNAP_IN_PLANE)); #endif macroRec->Disable(); // JBW 4/23/99 createInterface->SetNodeTMRelConstPlane(targNode, mat); macroRec->Enable(); createInterface->RedrawViews(createInterface->GetTime()); macroRec->SetProperty(lgtObject, _T("target"), // JBW 4/23/99 mr_create, Class_ID(TARGET_CLASS_ID, 0), GEOMOBJECT_CLASS_ID, 1, _T("transform"), mr_matrix3, &mat); res = TRUE; break; case MOUSE_FREEMOVE: SetCursor(LoadCursor(hInstance, MAKEINTRESOURCE(IDC_CROSS_HAIR))); #ifdef _OSNAP //Snap Preview #ifdef _3D_CREATE vpx->SnapPreview(m,m,NULL, SNAP_IN_3D); #else vpx->SnapPreview(m,m,NULL, SNAP_IN_PLANE); #endif #endif vpx->TrackImplicitGrid(m); //KENNY MERGE break; case MOUSE_PROPCLICK: // right click while between creations createInterface->RemoveMode(NULL); break; case MOUSE_ABORT: abort: assert( lgtObject ); lgtObject->EndEditParams( (IObjParam*)createInterface,0,NULL); // Toss the undo stack if param changes have been made macroRec->Cancel(); // JBW 4/23/99 theHold.Cancel(); // deletes both the camera and target. if (needToss) GetSystemSetting(SYSSET_CLEAR_UNDO); lgtNode = NULL; targNode = NULL; createInterface->RedrawViews(createInterface->GetTime()); CreateNewObject(); attachedToNode = FALSE; res = FALSE; } done: //KENNY MERGE if ((res == CREATE_STOP)||(res==CREATE_ABORT)) vpx->ReleaseImplicitGrid(); createInterface->ReleaseViewport(vpx); return res; } #endif