AlphaModifier.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project name : Buccaneer Bay *
  23. * *
  24. * File name : AlphaModifier.cpp *
  25. * *
  26. * Programmer : Mike Lytle *
  27. * *
  28. * Start date : 11/1/1999 *
  29. * *
  30. * Last update : 11/1/1999 *
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "AlphaModifier.h"
  36. enum Alpha_Messages
  37. {
  38. AM_NOTHING,
  39. AM_UPDATE_DATA,
  40. AM_INITIALIZE,
  41. AM_BOX_CHECKED,
  42. };
  43. enum Dialog_Controls
  44. {
  45. DL_EDIT_VALUE,
  46. DL_FIND_CHECK_BOX,
  47. };
  48. void AlphaModifierClass::ModifyObject(TimeValue t, ModContext &mc, ObjectState *os, INode *node)
  49. {
  50. if (!os->obj->IsSubClassOf(triObjectClassID))
  51. {
  52. return;
  53. }
  54. // Get a mesh from input object
  55. TriObject *object = (TriObject*)os->obj;
  56. Mesh *mesh = &object->mesh;
  57. assert(mesh);
  58. int numVert = mesh->getNumVerts();
  59. int i = 0;
  60. float *vdata = NULL;
  61. // Get parameters from pblock
  62. float sparam = 0.0f;
  63. Interval valid = LocalValidity(t);
  64. int pass = 1;
  65. pblock->GetValue(DL_EDIT_VALUE, t, sparam, valid);
  66. // If needed a control could be put into the dialog box to specify which
  67. // pass to apply the alpha values to. At this time, it was decided to
  68. // not implement this because of the complexity to the artist and the
  69. // performance issues in game.
  70. //pblock->GetValue(DL_EDIT_PASS, t, pass, valid);
  71. // Start from 0.
  72. pass -= 1;
  73. assert(pass >= 0);
  74. // Use a channel for each pass.
  75. vdata = mesh->vertexFloat(ALPHA_VERTEX_CHANNEL + pass);
  76. if (!vdata)
  77. {
  78. // Turn on the channel for vertex alpha support.
  79. mesh->setVDataSupport(ALPHA_VERTEX_CHANNEL + pass);
  80. vdata = mesh->vertexFloat(ALPHA_VERTEX_CHANNEL + pass);
  81. assert(vdata);
  82. for (i = 0; i < numVert; i++)
  83. {
  84. if (mesh->VertSel()[i])
  85. {
  86. vdata[i] = 0.0f;
  87. }
  88. }
  89. }
  90. // Tracks the state of the FIND check box.
  91. int box_checked = 0;
  92. if (Message == AM_UPDATE_DATA)
  93. {
  94. // The user has updated the dialog box, so update the data.
  95. assert(vdata);
  96. pblock->GetValue(DL_FIND_CHECK_BOX, t, box_checked, valid);
  97. if (!box_checked)
  98. {
  99. for (i = 0; i < numVert; i++)
  100. {
  101. if (SelectedVertices[i])
  102. {
  103. vdata[i] = sparam;
  104. }
  105. }
  106. }
  107. }
  108. if (Message == AM_BOX_CHECKED)
  109. {
  110. pblock->GetValue(DL_FIND_CHECK_BOX, t, box_checked, valid);
  111. }
  112. // The user is trying to find vertices with certain values.
  113. if (box_checked)
  114. {
  115. assert(vdata);
  116. // Find the vertices that have the user entered value.
  117. for (i = 0; i < numVert; i++)
  118. {
  119. if (vdata[i] == sparam)
  120. {
  121. mesh->VertSel().Set(i);
  122. SelectedVertices.Set(i);
  123. }
  124. else
  125. {
  126. mesh->VertSel().Clear(i);
  127. SelectedVertices.Clear(i);
  128. }
  129. }
  130. }
  131. if (Message == AM_INITIALIZE)
  132. {
  133. assert(vdata);
  134. SelectedVertices = mesh->VertSel();
  135. for (i = 0; i < numVert; i++)
  136. {
  137. if (SelectedVertices[i])
  138. {
  139. // Set the value in the dialog box to the value of the
  140. // first selected vertex.
  141. pblock->SetValue(DL_EDIT_VALUE, t, vdata[i]);
  142. break;
  143. }
  144. }
  145. }
  146. // Always select the vertices that have been saved by the modifier.
  147. // This must be done because the mesh changes each time ModfiyObject is called.
  148. for (i = 0; i < numVert; i++)
  149. {
  150. if (SelectedVertices[i])
  151. {
  152. mesh->VertSel().Set(i);
  153. }
  154. else
  155. {
  156. mesh->VertSel().Clear(i);
  157. }
  158. }
  159. // Display the vertices.
  160. mesh->SetDispFlag(DISP_SELVERTS | DISP_VERTTICKS);
  161. mesh->selLevel = MESH_VERTEX;
  162. object->UpdateValidity(SELECT_CHAN_NUM, object->ChannelValidity (t, SELECT_CHAN_NUM));
  163. // Clear messages.
  164. Message = AM_NOTHING;
  165. }
  166. /*===========================================================================*\
  167. | NotifyInputChanged is called each time the input object is changed in some way
  168. | We can find out how it was changed by checking partID and message
  169. \*===========================================================================*/
  170. void AlphaModifierClass::NotifyInputChanged(Interval changeInt, PartID partID, RefMessage message, ModContext *mc)
  171. {
  172. if( (partID&PART_TOPO) || (partID&PART_GEOM) || (partID&PART_SELECT) )
  173. {
  174. NotifyDependents(FOREVER, PART_OBJ, REFMSG_CHANGE);
  175. }
  176. }
  177. /*===========================================================================*\
  178. | Class Descriptor OSM
  179. \*===========================================================================*/
  180. class AlphaClassDesc : public ClassDesc2 {
  181. public:
  182. int IsPublic() { return TRUE; }
  183. void * Create( BOOL loading ) { return new AlphaModifierClass; }
  184. const TCHAR * ClassName() { return Get_String(IDS_ALPHA_MODIFIER_CLASS); }
  185. SClass_ID SuperClassID() { return OSM_CLASS_ID; }
  186. Class_ID ClassID() { return ALPHA_MODIFIER_CLASSID; }
  187. const TCHAR* Category() { return _T(""); }
  188. HINSTANCE HInstance() { return AppInstance; }
  189. // Hardwired name, used by MAX Script as unique identifier
  190. const TCHAR* InternalName() { return _T("AlphaMod"); }
  191. };
  192. static AlphaClassDesc AlphaCD;
  193. ClassDesc* Get_Alpha_Desc() {return &AlphaCD;}
  194. /*===========================================================================*\
  195. | Paramblock2 Descriptor
  196. \*===========================================================================*/
  197. static ParamBlockDesc2 alpha_param_blk
  198. (
  199. //rollout
  200. 0, _T("AlphaModifierParams"), 0, &AlphaCD, P_AUTO_CONSTRUCT + P_AUTO_UI, 0,
  201. IDD_ALPHA_MODIFIER, IDS_PARAMETERS, 0, 0, NULL,
  202. // params
  203. DL_EDIT_VALUE, _T("Custom Data Value"), TYPE_FLOAT, P_ANIMATABLE, IDS_ALPHA_MODIFIER_CLASS,
  204. p_default, 0.0f,
  205. p_range, 0.0f, 100.0f,
  206. p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, IDC_ALPHA_EDIT, IDC_ALPHA_SPIN, 1.0f,
  207. end,
  208. DL_FIND_CHECK_BOX, _T("1 Custom Data Value"), TYPE_BOOL, 0, IDS_ALPHA_MODIFIER_CLASS,
  209. p_default, FALSE,
  210. p_ui, TYPE_SINGLECHEKBOX, IDC_ALPHA_CHECKBOX,
  211. p_enabled, TRUE,
  212. end,
  213. /*
  214. DL_EDIT_PASS, _T("2 Custom Data Value"), TYPE_INT, P_ANIMATABLE, IDS_ALPHA_MODIFIER_CLASS,
  215. p_default, 1,
  216. p_range, 1, 4,
  217. p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_ALPHA_EDIT2, IDC_ALPHA_SPIN2, 1.0,
  218. end,
  219. */
  220. end
  221. );
  222. /*===========================================================================*\
  223. | Basic implementation of a dialog handler
  224. \*===========================================================================*/
  225. BOOL AlphaModDlgProc::DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  226. {
  227. int id = LOWORD(wParam);
  228. int code = HIWORD(wParam);
  229. switch (msg)
  230. {
  231. case WM_INITDIALOG:
  232. AlphaModifier->Message = AM_INITIALIZE;
  233. break;
  234. case WM_DESTROY:
  235. break;
  236. case WM_COMMAND:
  237. switch (code)
  238. {
  239. case EN_UPDATE:
  240. break;
  241. case EN_SETFOCUS:
  242. break;
  243. case EN_KILLFOCUS:
  244. break;
  245. case EN_CHANGE:
  246. break;
  247. }
  248. if (id == IDC_ALPHA_EDIT)
  249. {
  250. AlphaModifier->Message = AM_UPDATE_DATA;
  251. }
  252. if (id == IDC_ALPHA_CHECKBOX)
  253. {
  254. AlphaModifier->Message = AM_BOX_CHECKED;
  255. }
  256. break;
  257. case WM_NOTIFY:
  258. if (id == IDC_ALPHA_EDIT)
  259. {
  260. AlphaModifier->Message = AM_UPDATE_DATA;
  261. }
  262. break;
  263. default:
  264. break;
  265. }
  266. return FALSE;
  267. }
  268. /*===========================================================================*\
  269. | Constructor
  270. | Ask the ClassDesc2 to make the AUTO_CONSTRUCT paramblocks and wire them in
  271. \*===========================================================================*/
  272. AlphaModifierClass::AlphaModifierClass()
  273. {
  274. AlphaCD.MakeAutoParamBlocks(this);
  275. assert(pblock);
  276. Message = 0;
  277. }
  278. /*===========================================================================*\
  279. | Invalidate our UI (or the recently changed parameter)
  280. \*===========================================================================*/
  281. void AlphaModifierClass::InvalidateUI()
  282. {
  283. alpha_param_blk.InvalidateUI(pblock->LastNotifyParamID());
  284. }
  285. /*===========================================================================*\
  286. | Open and Close dialog UIs
  287. | We ask the ClassDesc2 to handle Beginning and Ending EditParams for us
  288. \*===========================================================================*/
  289. void AlphaModifierClass::BeginEditParams( IObjParam *ip, ULONG flags,Animatable *prev )
  290. {
  291. AlphaCD.BeginEditParams(ip, this, flags, prev);
  292. alpha_param_blk.SetUserDlgProc(new AlphaModDlgProc(this));
  293. }
  294. void AlphaModifierClass::EndEditParams( IObjParam *ip, ULONG flags,Animatable *next )
  295. {
  296. AlphaCD.EndEditParams(ip, this, flags, next);
  297. }
  298. /*===========================================================================*\
  299. | Standard clone
  300. \*===========================================================================*/
  301. RefTargetHandle AlphaModifierClass::Clone(RemapDir& remap)
  302. {
  303. AlphaModifierClass* newmod = new AlphaModifierClass();
  304. newmod->ReplaceReference(0,pblock->Clone(remap));
  305. return(newmod);
  306. }
  307. /*===========================================================================*\
  308. | Subanim & References support
  309. \*===========================================================================*/
  310. Animatable* AlphaModifierClass::SubAnim(int i)
  311. {
  312. switch (i)
  313. {
  314. case 0: return pblock;
  315. default: return NULL;
  316. }
  317. }
  318. TSTR AlphaModifierClass::SubAnimName(int i)
  319. {
  320. switch (i)
  321. {
  322. case 0: return Get_String(IDS_PARAMETERS);
  323. default: return _T("");
  324. }
  325. }
  326. RefTargetHandle AlphaModifierClass::GetReference(int i)
  327. {
  328. switch (i)
  329. {
  330. case 0: return pblock;
  331. default:
  332. assert(TRUE);
  333. return NULL;
  334. }
  335. }
  336. void AlphaModifierClass::SetReference(int i, RefTargetHandle rtarg)
  337. {
  338. switch (i)
  339. {
  340. case 0: pblock = (IParamBlock2*)rtarg; break;
  341. default:
  342. assert(TRUE);
  343. break;
  344. }
  345. }
  346. RefResult AlphaModifierClass::NotifyRefChanged
  347. (
  348. Interval changeInt,
  349. RefTargetHandle hTarget,
  350. PartID& partID,
  351. RefMessage message
  352. )
  353. {
  354. switch (message)
  355. {
  356. case REFMSG_CHANGE:
  357. {
  358. alpha_param_blk.InvalidateUI();
  359. }
  360. break;
  361. }
  362. return REF_SUCCEED;
  363. }
  364. /*===========================================================================*\
  365. | The validity of our parameters
  366. | Start at FOREVER, and intersect with the validity of each item
  367. \*===========================================================================*/
  368. Interval AlphaModifierClass::GetValidity(TimeValue t)
  369. {
  370. float f;
  371. Interval valid = FOREVER;
  372. pblock->GetValue(DL_EDIT_VALUE, t, f, valid);
  373. return valid;
  374. }
  375. Interval AlphaModifierClass::LocalValidity(TimeValue t)
  376. {
  377. return GetValidity(t);
  378. }