1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2019 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "tile_utility.h"
22 extern HINSTANCE hInstance
;
23 TCHAR
*GetString(int id
);
25 #define NSUBTEX 2 // number of texture map slots
28 static int subTexId
[NSUBTEX
] = { IDC_MULT_TEX1
, IDC_MULT_TEX2
};
30 #define ALPHA_FROM_1 0
31 #define ALPHA_FROM_2 1
32 #define ALPHA_FROM_MULT 2
34 //--------------------------------------------------------------
35 // RGBAdd: A Composite texture map
36 //--------------------------------------------------------------
37 class RGBAdd
: public Texmap
{
40 IParamBlock2
*pblock
; // ref #0
41 Texmap
* subTex
[NSUBTEX
]; // refs 1,2;
49 ParamDlg
* CreateParamDlg(HWND hwMtlEdit
, IMtlParams
*imp
);
50 void Update(TimeValue t
, Interval
& valid
);
53 Interval
Validity(TimeValue t
) { Interval v
; Update(t
,v
); return ivalid
; }
57 void SetColor(int i
, Color c
, TimeValue t
);
59 // Evaluate the color of map for the context.
60 AColor
EvalColor(ShadeContext
& sc
);
61 float EvalMono(ShadeContext
& sc
);
62 AColor
EvalFunction(ShadeContext
& sc
, float u
, float v
, float du
, float dv
);
64 // For Bump mapping, need a perturbation to apply to a normal.
65 // Leave it up to the Texmap to determine how to do this.
66 Point3
EvalNormalPerturb(ShadeContext
& sc
);
68 // Methods to access texture maps of material
69 int NumSubTexmaps() { return NSUBTEX
; }
70 Texmap
* GetSubTexmap(int i
) { return subTex
[i
]; }
71 void SetSubTexmap(int i
, Texmap
*m
);
72 TSTR
GetSubTexmapSlotName(int i
);
74 Class_ID
ClassID() { return RGBAddClassID
; }
75 SClass_ID
SuperClassID() { return TEXMAP_CLASS_ID
; }
76 void GetClassName(TSTR
& s
) { s
= _T("RGB Additive"); }
77 void DeleteThis() { delete this; }
79 int NumSubs() { return NSUBTEX
+1; }
80 Animatable
* SubAnim(int i
);
81 TSTR
SubAnimName(int i
);
82 int SubNumToRefNum(int subNum
) { return subNum
; }
85 int NumRefs() { return NSUBTEX
+1; }
86 RefTargetHandle
GetReference(int i
);
87 void SetReference(int i
, RefTargetHandle rtarg
);
88 int RemapRefOnLoad(int iref
);
90 RefTargetHandle
Clone(RemapDir
&remap
= DefaultRemapDir());
91 RefResult
NotifyRefChanged(NOTIFY_REF_PARAMS
);
94 IOResult
Save(ISave
*isave
);
95 IOResult
Load(ILoad
*iload
);
97 // JBW: direct ParamBlock access is added
98 int NumParamBlocks() { return 1; } // return number of ParamBlocks in this instance
99 IParamBlock2
* GetParamBlock(int i
) { return pblock
; } // return i'th ParamBlock
100 IParamBlock2
* GetParamBlockByID(BlockID id
) { return (pblock
->ID() == id
) ? pblock
: NULL
; } // return id'd ParamBlock
105 class RGBAddClassDesc
:public ClassDesc2
{
107 int IsPublic() { return 1; }
108 void * Create(BOOL loading
) { return new RGBAdd
; }
109 const TCHAR
* ClassName() { return GetString(IDS_DS_RGBMULT_CDESC
); } // mjm - 2.3.99
110 SClass_ID
SuperClassID() { return TEXMAP_CLASS_ID
; }
111 Class_ID
ClassID() { return RGBAddClassID
; }
112 const MCHAR
* Category() { return TEXMAP_CAT_COMP
; }
113 // JBW: new descriptor data accessors added. Note that the
114 // internal name is hardwired since it must not be localized.
115 const MCHAR
* InternalName() { return _M("RGBAdd"); } // returns fixed parsable name (scripter-visible name)
116 HINSTANCE
HInstance() { return hInstance
; } // returns owning module handle
119 static RGBAddClassDesc maskCD
;
121 ClassDesc
* GetRGBAddDesc() { return &maskCD
; }
123 enum { RGBAdd_params
}; // pblock ID
124 // RGBAdd_params param IDs
127 RGBAdd_color1
, RGBAdd_color2
,
128 RGBAdd_map1
, RGBAdd_map2
,
129 RGBAdd_map1_on
, RGBAdd_map2_on
, // main grad params
134 static ParamBlockDesc2
RGBAdd_param_blk ( RGBAdd_params
, _T("parameters"), 0, &maskCD
, P_AUTO_CONSTRUCT
+ P_AUTO_UI
, 0,
136 IDD_RGBMULT
, _T("RGB Additif Parameters"), 0, 0, NULL
,
138 RGBAdd_color1
, _T("color1"), TYPE_RGBA
, P_ANIMATABLE
, IDS_DS_COLOR1
,
139 p_default
, Color(0,0,0),
140 p_ui
, TYPE_COLORSWATCH
, IDC_MULT_COL1
,
142 RGBAdd_color2
, _T("color2"), TYPE_RGBA
, P_ANIMATABLE
, IDS_DS_COLOR2
,
143 p_default
, Color(0.5,0.5,0.5),
144 p_ui
, TYPE_COLORSWATCH
, IDC_MULT_COL2
,
146 RGBAdd_map1
, _T("map1"), TYPE_TEXMAP
, P_OWNERS_REF
, IDS_JW_MAP1
,
149 p_ui
, TYPE_TEXMAPBUTTON
, IDC_MULT_TEX1
,
151 RGBAdd_map2
, _T("map2"), TYPE_TEXMAP
, P_OWNERS_REF
, IDS_JW_MAP2
,
154 p_ui
, TYPE_TEXMAPBUTTON
, IDC_MULT_TEX2
,
156 RGBAdd_map1_on
, _T("map1Enabled"), TYPE_BOOL
, 0, IDS_JW_MAP1ENABLE
,
158 p_ui
, TYPE_SINGLECHEKBOX
, IDC_MAPON1
,
160 RGBAdd_map2_on
, _T("map2Enabled"), TYPE_BOOL
, 0, IDS_JW_MAP2ENABLE
,
162 p_ui
, TYPE_SINGLECHEKBOX
, IDC_MAPON2
,
164 RGBAdd_type
, _T("alphaFrom"), TYPE_INT
, 0, IDS_PW_ALPHAFROM
,
167 p_ui
, TYPE_RADIO
, 3, IDC_MULT_ALPHA1
, IDC_MULT_ALPHA2
, IDC_MULT_ALPHA3
,
174 //-----------------------------------------------------------------------------
176 //-----------------------------------------------------------------------------
179 static int name_id
[NPARAMS
] = {IDS_DS_COLOR1
, IDS_DS_COLOR2
};
181 #define RGBAdd_VERSION 2
182 static ParamBlockDescID pbdesc
[NPARAMS
] = {
183 { TYPE_RGBA
, NULL
, TRUE
,RGBAdd_color1
}, // col1
184 { TYPE_RGBA
, NULL
, TRUE
,RGBAdd_color2
} // col2
187 static ParamVersionDesc versions
[] = {
188 ParamVersionDesc(pbdesc
,2,1), // Version 1 params
192 void RGBAdd::Init() {
194 alphaFrom
= ALPHA_FROM_MULT
;
195 SetColor(0, Color(0.0f
,0.0f
,0.0f
), TimeValue(0));
196 SetColor(1, Color(0.0f
,0.0f
,0.0f
), TimeValue(0));
197 mapOn
[0] = mapOn
[1] = 1;
200 void RGBAdd::Reset() {
201 maskCD
.Reset(this, TRUE
); // reset all pb2's
202 DeleteReference(1); // get rid of maps
203 DeleteReference(2); // get rid of maps
207 void RGBAdd::NotifyChanged() {
208 NotifyDependents(FOREVER
, PART_ALL
, REFMSG_CHANGE
);
213 for (int i
=0; i
<NSUBTEX
; i
++) subTex
[i
] = NULL
;
215 maskCD
.MakeAutoParamBlocks(this); // make and intialize paramblock2
221 static AColor
white(1.0f
,1.0f
,1.0f
,1.0f
);
223 AColor
RGBAdd::EvalColor(ShadeContext
& sc
)
225 if (gbufID
) sc
.SetGBufferID(gbufID
);
226 AColor c0
= (subTex
[0]&&mapOn
[0])? subTex
[0]->EvalColor(sc
): col
[0];
227 AColor c1
= (subTex
[1]&&mapOn
[1])? subTex
[1]->EvalColor(sc
): col
[1];
230 c
.r
= c
.r
> 1.f
? 1.f
: c
.r
;
232 c
.g
= c
.g
> 1.f
? 1.f
: c
.g
;
234 c
.b
= c
.b
> 1.f
? 1.f
: c
.b
;
236 case ALPHA_FROM_1
: c
.a
= c0
.a
; break;
237 case ALPHA_FROM_2
: c
.a
= c1
.a
; break;
238 case ALPHA_FROM_MULT
: c
.a
= c0
.a
*c1
.a
; break;
243 float RGBAdd::EvalMono(ShadeContext
& sc
)
245 if (gbufID
) sc
.SetGBufferID(gbufID
);
246 float m
= (subTex
[1]&&mapOn
[1])? subTex
[1]->EvalMono(sc
): Intens(col
[0]);
247 float c0
= (subTex
[0]&&mapOn
[0])? subTex
[0]->EvalMono(sc
): Intens(col
[1]);
248 return (m
+c0
) > 1.f
? 1.f
: m
+c0
;
251 Point3
RGBAdd::EvalNormalPerturb(ShadeContext
& sc
) {
252 if (gbufID
) sc
.SetGBufferID(gbufID
);
253 Point3 p0
= subTex
[0]&&mapOn
[0]? subTex
[0]->EvalNormalPerturb(sc
): Point3(0.0f
,0.0f
,0.0f
);
254 Point3 p1
= subTex
[1]&&mapOn
[1]? subTex
[1]->EvalNormalPerturb(sc
): Point3(0.0f
,0.0f
,0.0f
);
258 RefTargetHandle
RGBAdd::Clone(RemapDir
&remap
) {
259 RGBAdd
*mnew
= new RGBAdd();
260 *((MtlBase
*)mnew
) = *((MtlBase
*)this); // copy superclass stuff
261 mnew
->ReplaceReference(0,remap
.CloneRef(pblock
));
262 mnew
->ivalid
.SetEmpty();
263 for (int i
= 0; i
<NSUBTEX
; i
++) {
264 mnew
->subTex
[i
] = NULL
;
266 mnew
->ReplaceReference(i
+1,remap
.CloneRef(subTex
[i
]));
267 mnew
->mapOn
[i
] = mapOn
[i
];
269 mnew
->alphaFrom
= alphaFrom
;
270 return (RefTargetHandle
)mnew
;
273 ParamDlg
* RGBAdd::CreateParamDlg(HWND hwMtlEdit
, IMtlParams
*imp
) {
274 IAutoMParamDlg
* masterDlg
= maskCD
.CreateParamDlgs(hwMtlEdit
, imp
, this);
279 void RGBAdd::Update(TimeValue t
, Interval
& valid
) {
283 pblock
->SetValue( RGBAdd_map1_on
, 0, mapOn
[0]);
284 pblock
->SetValue( RGBAdd_map2_on
, 0, mapOn
[1]);
285 pblock
->SetValue( RGBAdd_type
, 0, alphaFrom
);
289 if (!ivalid
.InInterval(t
)) {
290 ivalid
.SetInfinite();
291 pblock
->GetValue( RGBAdd_color1
, t
, col
[0], ivalid
);
292 col
[0].ClampMinMax();
293 pblock
->GetValue( RGBAdd_color2
, t
, col
[1], ivalid
);
295 pblock
->GetValue( RGBAdd_map1_on
, t
, mapOn
[0], ivalid
);
296 pblock
->GetValue( RGBAdd_map2_on
, t
, mapOn
[1], ivalid
);
297 pblock
->GetValue( RGBAdd_type
, t
, alphaFrom
, ivalid
);
300 col
[1].ClampMinMax();
301 for (int i
=0; i
<NSUBTEX
; i
++) {
303 subTex
[i
]->Update(t
,ivalid
);
309 void RGBAdd::SetColor(int i
, Color c
, TimeValue t
) {
311 int id
= i
==0?RGBAdd_color1
:RGBAdd_color2
;
312 pblock
->SetValue( id
, t
, c
);
315 RefTargetHandle
RGBAdd::GetReference(int i
) {
316 if (i
==0) return pblock
;
317 else return subTex
[i
-1];
320 int RGBAdd::RemapRefOnLoad(int iref
) {
326 void RGBAdd::SetReference(int i
, RefTargetHandle rtarg
) {
328 case 0: pblock
= (IParamBlock2
*)rtarg
; break;
329 default: subTex
[i
-1] = (Texmap
*)rtarg
; break;
333 void RGBAdd::SetSubTexmap(int i
, Texmap
*m
) {
334 ReplaceReference(i
+1,m
);
337 RGBAdd_param_blk
.InvalidateUI(RGBAdd_map1
);
342 RGBAdd_param_blk
.InvalidateUI(RGBAdd_map2
);
348 TSTR
RGBAdd::GetSubTexmapSlotName(int i
) {
350 case 0: return TSTR(GetString(IDS_DS_COLOR1
));
351 case 1: return TSTR(GetString(IDS_DS_COLOR2
));
352 default: return TSTR(_T(""));
356 Animatable
* RGBAdd::SubAnim(int i
) {
358 case 0: return pblock
;
359 default: return subTex
[i
-1];
363 TSTR
RGBAdd::SubAnimName(int i
) {
365 case 0: return TSTR(GetString(IDS_DS_PARAMETERS
));
366 default: return GetSubTexmapTVName(i
-1);
370 RefResult
RGBAdd::NotifyRefChanged(NOTIFY_REF_PARAMS
)
376 if (hTarget
== pblock
)
378 // see if this message came from a changing parameter in the pblock,
379 // if so, limit rollout update to the changing item and update any active viewport texture
380 ParamID changing_param
= pblock
->LastNotifyParamID();
381 RGBAdd_param_blk
.InvalidateUI(changing_param
);
382 // notify our dependents that we've changed
383 // NotifyChanged(); //DS this is redundant
392 #define MTL_HDR_CHUNK 0x4000
393 #define MAPOFF_CHUNK 0x1000
394 #define INVERT_RGBMULT_CHUNK 0x2000
395 #define ALPHA_FROM_CHUNK 0x2010
396 #define RGBAdd_VERSION_CHUNK 0x2020
397 #define PARAM2_CHUNK 0x2030
399 IOResult
RGBAdd::Save(ISave
*isave
) {
404 isave
->BeginChunk(MTL_HDR_CHUNK
);
405 res
= MtlBase::Save(isave
);
406 if (res
!=IO_OK
) return res
;
409 int vers
= RGBAdd_VERSION
;
410 isave
->BeginChunk(RGBAdd_VERSION_CHUNK
);
411 isave
->Write(&vers
,sizeof(vers
),&nb
);
414 isave
->BeginChunk(PARAM2_CHUNK
);
419 class RGBAddPostLoad
: public PostLoadCallback
{
422 RGBAddPostLoad(RGBAdd
*b
) {tm
=b
;}
423 void proc(ILoad
*iload
) { tm
->loadingOld
= FALSE
; delete this; }
426 class RGBAdd2PostLoad
: public PostLoadCallback
{
429 RGBAdd2PostLoad(RGBAdd
*ns
) {n
= ns
;}
430 void proc(ILoad
*iload
) {
433 n
->pblock
->SetValue( RGBAdd_map1_on
, 0, n
->mapOn
[0]);
434 n
->pblock
->SetValue( RGBAdd_map2_on
, 0, n
->mapOn
[1]);
435 n
->pblock
->SetValue( RGBAdd_type
, 0, n
->alphaFrom
);
445 IOResult
RGBAdd::Load(ILoad
*iload
) {
451 while (IO_OK
==(res
=iload
->OpenChunk())) {
452 switch(id
= iload
->CurChunkID()) {
454 res
= MtlBase::Load(iload
);
459 case RGBAdd_VERSION_CHUNK
:
464 mapOn
[id
-MAPOFF_CHUNK
] = 0;
466 case ALPHA_FROM_CHUNK
:
467 res
= iload
->Read(&alphaFrom
,sizeof(alphaFrom
), &nb
);
475 iload
->RegisterPostLoadCallback(new RGBAddPostLoad(this));
477 // JBW: register old version ParamBlock to ParamBlock2 converter
478 ParamBlock2PLCB
* plcb
= new ParamBlock2PLCB(versions
, 1, &RGBAdd_param_blk
, this, 0);
479 iload
->RegisterPostLoadCallback(plcb
);
481 // iload->RegisterPostLoadCallback(new RGBAdd2PostLoad(this));