Params.cpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. /******************************************************************************/
  4. Cache<EditObject> EditObjects;
  5. /******************************************************************************/
  6. /******************************************************************************/
  7. bool EditParam::old(C TimeStamp &now)C
  8. {
  9. return removed_time<now && name_time<now && type_time<now && value_time<now;
  10. }
  11. bool EditParam::equal(C EditParam &src)C
  12. {
  13. return removed_time==src.removed_time && name_time==src.name_time && type_time==src.type_time && value_time==src.value_time;
  14. }
  15. bool EditParam::newer(C EditParam &src)C
  16. {
  17. return removed_time>src.removed_time || name_time>src.name_time || type_time>src.type_time || value_time>src.value_time;
  18. }
  19. uint EditParam::memUsage()C {return ::EE::Param::memUsage();}
  20. bool EditParam::contains(C Str &text, Project &proj)C
  21. {
  22. if(Contains(name, text))return true;
  23. if(type==PARAM_STR && Contains(value.s, text))return true;
  24. if(ParamTypeID(type))REP(IDs())if(Contains(proj.elmFullName(asID(i)), text))return true;
  25. return false;
  26. }
  27. EditParam& EditParam::create(C Param &src, C TimeStamp &time)
  28. {
  29. SCAST(Param, T)=src;
  30. removed=false;
  31. removed_time=name_time=type_time=value_time=time;
  32. return T;
  33. }
  34. void EditParam::setRemoved( bool removed ) {T.removed=removed; removed_time.getUTC();}
  35. EditParam& EditParam::setName(C Str &name ) {T.name =name ; name_time.getUTC(); return T;}
  36. void EditParam::clearValue( ) {if(type==PARAM_ID)setAsIDArray(null);else{::EE::Param::clearValue(); value_time.getUTC();}}
  37. void EditParam::setBool( bool v ) {value.b=v; value_time.getUTC();}
  38. void EditParam::setColor(C Color &v ) {value.c=v; value_time.getUTC();}
  39. void EditParam::setValue( int v ) {::EE::Param::setValue(v); value_time.getUTC();}
  40. void EditParam::setValue(C Str &v ) {::EE::Param::setValue(v); value_time.getUTC();}
  41. EditParam& EditParam::forceBool( bool v ) {setType(PARAM_BOOL ); value.b=v; value_time.getUTC(); return T;}
  42. EditParam& EditParam::forceInt( int v ) {setType(PARAM_INT ); value.i=v; value_time.getUTC(); return T;}
  43. EditParam& EditParam::forceFlt( flt v ) {setType(PARAM_FLT ); value.f=v; value_time.getUTC(); return T;}
  44. EditParam& EditParam::forceColor(C Color &v ) {setType(PARAM_COLOR); value.c=v; value_time.getUTC(); return T;}
  45. EditParam& EditParam::setAsIDArray(C MemPtr<UID> &ids ) {::EE::Param:: setAsIDArray(ids); type_time.getUTC(); value_time.getUTC(); return T;}
  46. EditParam& EditParam::includeAsIDArray(C MemPtr<UID> &ids ) {::EE::Param::includeAsIDArray(ids); type_time.getUTC(); value_time.getUTC(); return T;}
  47. EditParam& EditParam::setType(PARAM_TYPE type, Enum *enum_type) {::EE::Param::setType((type==PARAM_ID) ? PARAM_ID_ARRAY : type, enum_type); type_time.getUTC(); return T;}
  48. EditParam& EditParam::setTypeValue(C Param &src ) {::EE::Param::setTypeValue(src); type_time.getUTC(); value_time.getUTC(); return T;}
  49. void EditParam::nameTypeValueUTC( ) {name_time.getUTC(); type_time.getUTC(); value_time.getUTC();}
  50. bool EditParam::sync(C EditParam &src)
  51. {
  52. bool changed=false;
  53. changed|=Sync(removed_time, src.removed_time, removed, src.removed);
  54. changed|=Sync( name_time, src. name_time, name , src.name );
  55. if(Sync(type_time, src.type_time)) // adjust type first before the value
  56. {
  57. changed=true;
  58. ::EE::Param::setType(src.type, src.enum_type);
  59. }
  60. if(Sync(value_time, src.value_time))
  61. {
  62. changed=true;
  63. ::EE::Param::setValue(src);
  64. }
  65. return changed;
  66. }
  67. bool EditParam::undo(C EditParam &src)
  68. {
  69. bool changed=false;
  70. changed|=Undo(removed_time, src.removed_time, removed, src.removed);
  71. changed|=Undo( name_time, src. name_time, name , src.name );
  72. if(Undo(type_time, src.type_time)) // adjust type first before the value
  73. {
  74. changed=true;
  75. ::EE::Param::setType(src.type, src.enum_type);
  76. }
  77. if(Undo(value_time, src.value_time))
  78. {
  79. changed=true;
  80. ::EE::Param::setValue(src);
  81. }
  82. return changed;
  83. }
  84. bool EditParam::save(File &f, cchar *game_path)C
  85. {
  86. f.cmpUIntV(0);
  87. f<<id<<removed<<removed_time<<name_time<<type_time<<value_time;
  88. ::EE::Param::save(f, game_path);
  89. return f.ok();
  90. }
  91. bool EditParam::load(File &f, cchar *game_path)
  92. {
  93. switch(f.decUIntV())
  94. {
  95. case 0:
  96. {
  97. f>>id>>removed>>removed_time>>name_time>>type_time>>value_time;
  98. if(::EE::Param::load(f, game_path))
  99. if(f.ok())return true;
  100. }break;
  101. }
  102. return false;
  103. }
  104. EditParam* EditParams::findParam(C UID &id ) {REPA(T){EditParam &p=T[i]; if( p.id==id )return &p;} return null;}
  105. EditParam* EditParams::findParam(C Str &name ) {REPA(T){EditParam &p=T[i]; if(!p.removed && p.name==name )return &p;} return null;}
  106. EditParam* EditParams::findParam(C Str &name, PARAM_TYPE type) {REPA(T){EditParam &p=T[i]; if(!p.removed && p.name==name && ParamTypeCompatible(p.type, type))return &p;} return null;}
  107. C EditParam* EditParams::findParam(C UID &id )C {return ConstCast(T).findParam(id);}
  108. C EditParam* EditParams::findParam(C Str &name )C {return ConstCast(T).findParam(name);}
  109. C EditParam* EditParams::findParam(C Str &name, PARAM_TYPE type)C {return ConstCast(T).findParam(name, type);}
  110. EditParam* EditParams::findParamInclRemoved(C Str &name ) {EditParam *ret=null; REPA(T){EditParam &p=T[i]; if(p.name==name ){ret=&p; if(!p.removed)break;}} return ret;}
  111. EditParam* EditParams::findParamInclRemoved(C Str &name, PARAM_TYPE type) {EditParam *ret=null; REPA(T){EditParam &p=T[i]; if(p.name==name && ParamTypeCompatible(p.type, type)){ret=&p; if(!p.removed)break;}} return ret;}
  112. uint EditParams::memUsage()C
  113. {
  114. uint size=0; REPA(T)size+=T[i].memUsage();
  115. return size;
  116. }
  117. bool EditParams::old(C TimeStamp &now)C
  118. {
  119. REPA(T)if(!T[i].old(now))return false;
  120. return true;
  121. }
  122. bool EditParams::equal(C EditParams &src)C
  123. {
  124. if(elms()==src.elms())
  125. {
  126. REPA(T)
  127. {
  128. C EditParam &param=T[i], *src_param=src.findParam(param.id);
  129. if(!src_param || !param.equal(*src_param))return false;
  130. }
  131. return true;
  132. }
  133. return false;
  134. }
  135. bool EditParams::newer(C EditParams &src)C
  136. {
  137. REPA(T)
  138. {
  139. C EditParam &param=T[i], *src_param=src.findParam(param.id);
  140. if(!src_param || param.newer(*src_param))return true;
  141. }
  142. return false;
  143. }
  144. void EditParams::create(C EditParams &src)
  145. {
  146. FREPA(src)if(!src[i].removed)add(src[i]);
  147. }
  148. void EditParams::create(C Object &src, C TimeStamp &time)
  149. {
  150. clear(); FREPA(src.params)New().create(src.params[i], time);
  151. }
  152. void EditParams::copyTo(Object &obj)C
  153. {
  154. obj.params.del(); FREPA(T)if(!T[i].removed)obj.params.New()=T[i]; obj.sortParams();
  155. }
  156. bool EditParams::sync(C EditParams &src)
  157. {
  158. bool changed=false;
  159. FREPA(T) // sync same params
  160. {
  161. EditParam &param=T[i];
  162. if(C EditParam *src_param=src.findParam(param.id))changed|=param.sync(*src_param);
  163. }
  164. FREPA(src) // add new params from src
  165. {
  166. C EditParam &src_param=src[i];
  167. if(!findParam(src_param.id)){changed=true; add(src_param);}
  168. }
  169. return changed;
  170. }
  171. bool EditParams::undo(C EditParams &src)
  172. {
  173. bool changed=false;
  174. // mark as removed those that aren't present in 'src'
  175. REPA(T)
  176. {
  177. EditParam &param=T[i]; if(!param.removed && !src.findParam(param.id)){param.removed=true; param.removed_time++; changed=true;}
  178. }
  179. // undo/insert from 'src'
  180. REPA(src)
  181. {
  182. C EditParam &s=src[i];
  183. EditParam *t=findParam(s.id);
  184. if(t)changed|=t->undo(s);else{add(s); changed=true;}
  185. }
  186. return changed;
  187. }
  188. bool EditParams::save(File &f, cchar *game_path)C
  189. {
  190. f.cmpUIntV(0);
  191. return ::EE::Memc< ::EditParam>::save(f, game_path);
  192. }
  193. bool EditParams::load(File &f, cchar *game_path)
  194. {
  195. switch(f.decUIntV())
  196. {
  197. case 0: return ::EE::Memc< ::EditParam>::load(f, game_path);
  198. }
  199. return false;
  200. }
  201. bool EditObject::SubObj::old(C TimeStamp &now)C {return removed_time<now;}
  202. bool EditObject::SubObj::equal(C SubObj &src )C {return removed_time==src.removed_time;}
  203. bool EditObject::SubObj::newer(C SubObj &src )C {return removed_time> src.removed_time;}
  204. void EditObject::SubObj::setRemoved(bool removed) {T.removed=removed; removed_time.getUTC();}
  205. bool EditObject::SubObj::sync(C SubObj &src) {return Sync(removed_time, src.removed_time, removed, src.removed);}
  206. bool EditObject::SubObj::undo(C SubObj &src) {return Undo(removed_time, src.removed_time, removed, src.removed);}
  207. bool EditObject::SubObj::save(File &f)C
  208. {
  209. f.cmpUIntV(0);
  210. f<<removed<<removed_time<<id<<elm_obj_id;
  211. return f.ok();
  212. }
  213. bool EditObject::SubObj::load(File &f)
  214. {
  215. switch(f.decUIntV())
  216. {
  217. case 0:
  218. {
  219. f>>removed>>removed_time>>id>>elm_obj_id;
  220. if(f.ok())return true;
  221. }break;
  222. }
  223. return false;
  224. }
  225. bool EditObject::constant()C {return FlagTest(flag, CONSTANT);}
  226. uint EditObject::memUsage()C {return ::EditParams::memUsage()+sub_objs.memUsage();}
  227. ::EditObject::SubObj* EditObject::findSubObj(C UID &id) {REPA(sub_objs)if(sub_objs[i].id==id)return &sub_objs[i]; return null;}
  228. C ::EditObject::SubObj* EditObject::findSubObj(C UID &id)C {return ConstCast(T).findSubObj(id);}
  229. void EditObject::del()
  230. {
  231. ::EE::Memc< ::EditParam>::del();
  232. flag=0;
  233. type.zero();
  234. editor_type.zero();
  235. access=OBJ_ACCESS_TERRAIN;
  236. path =OBJ_PATH_CREATE;
  237. mesh_variation_id=0;
  238. base_time=access_time=type_time=editor_type_time=const_time=path_time=mesh_variation_time=0;
  239. base=null;
  240. }
  241. C EditParam* EditObject::findParam(C Str &name)C
  242. {
  243. Memt<C EditObject*> bases;
  244. for(C EditObject *cur=this; cur && bases.include(cur); cur=cur->base())if(C EditParam *param=cur->EditParams::findParam(name))return param; // check self and bases
  245. if(C Memc<GuiEditParam> *params=EditObjType.findParams(editor_type))REPA(*params)if((*params)[i].name==name)return &(*params)[i]; // check editor type
  246. return null;
  247. }
  248. C EditParam* EditObject::baseFindParam(C Str &name, PARAM_TYPE type)C
  249. {
  250. Memt<C EditObject*> bases;
  251. for(C EditObject *cur=base(); cur && bases.include(cur); cur=cur->base())if(C EditParam *param=cur->EditParams::findParam(name, type))return param; // check bases (skip self)
  252. if(C Memc<GuiEditParam> *params=EditObjType.findParams(editor_type))REPA(*params)if((*params)[i].name==name && ParamTypeCompatible((*params)[i].type, type))return &(*params)[i]; // check editor type
  253. return null;
  254. }
  255. bool EditObject::paramValuesContain(C Str &text, Project &proj)C
  256. {
  257. Memt<C EditObject*> bases;
  258. for(C EditObject *cur=this; cur && bases.include(cur); cur=cur->base()) // check self and bases
  259. {
  260. REPA(*cur) // iterate all params of this base
  261. if(C EditParam *param=findParam((*cur)[i].name)) // use 'this' for 'findParam' (instead of 'cur') because we want to get only overriden values
  262. if(param->contains(text, proj))return true;
  263. }
  264. if(C Memc<GuiEditParam> *params=EditObjType.findParams(editor_type)) // check editor type
  265. {
  266. REPA(*params)
  267. if(C EditParam *param=findParam((*params)[i].name)) // use 'this' for 'findParam' (instead of 'params') because we want to get only overriden values
  268. if(param->contains(text, proj))return true;
  269. }
  270. return false;
  271. }
  272. bool EditObject::hasBase(C UID &obj_id)C
  273. {
  274. if(obj_id.valid())
  275. {
  276. Memt<C EditObject*> bases;
  277. for(C EditObject *cur=this; cur && bases.include(cur); cur=cur->base()) // check self and bases
  278. if(EditObjects.id(cur)==obj_id)return true;
  279. }
  280. return false;
  281. }
  282. EditObject& EditObject::setBase(C EditObjectPtr &base, cchar *edit_path)
  283. {
  284. base_time.getUTC();
  285. T.base=base;
  286. updateBase(edit_path);
  287. return T;
  288. }
  289. EditObject& EditObject::setAccess(bool custom, OBJ_ACCESS access)
  290. {
  291. access_time.getUTC();
  292. FlagSet(flag, OVR_ACCESS, custom);
  293. T.access=(custom ? access : base ? base->access : OBJ_ACCESS_TERRAIN);
  294. return T;
  295. }
  296. EditObject& EditObject::setType(bool custom, C UID &type, cchar *edit_path)
  297. {
  298. type_time.getUTC();
  299. FlagSet(flag, OVR_TYPE, custom);
  300. if(custom)T.type=type;else if(base)T.type=base->type;else T.type.zero();
  301. updateEditorType(edit_path);
  302. return T;
  303. }
  304. EditObject& EditObject::setEditorType(C UID &type)
  305. {
  306. T.editor_type_time.getUTC();
  307. T.editor_type =type;
  308. return T;
  309. }
  310. EditObject& EditObject::setConst(bool custom, bool on)
  311. {
  312. const_time.getUTC();
  313. FlagSet(flag, OVR_CONST, custom);
  314. FlagSet(flag, CONSTANT, custom ? on : base ? base->constant() : false);
  315. return T;
  316. }
  317. EditObject& EditObject::setPath(bool custom, OBJ_PATH path)
  318. {
  319. path_time.getUTC();
  320. FlagSet(flag, OVR_PATH, custom);
  321. T.path=(custom ? path : base ? base->path : OBJ_PATH_CREATE);
  322. return T;
  323. }
  324. EditObject& EditObject::setMeshVariation(bool custom, uint mesh_variation_id)
  325. {
  326. mesh_variation_time.getUTC();
  327. FlagSet(flag, OVR_MESH_VARIATION, custom);
  328. T.mesh_variation_id=(custom ? mesh_variation_id : base ? base->mesh_variation_id : 0);
  329. return T;
  330. }
  331. bool EditObject::subObjsOld(C TimeStamp &now)C {REPA(sub_objs)if(!sub_objs[i].old(now))return false; return true;}
  332. bool EditObject::subObjsEqual(C EditObject &src)C
  333. {
  334. if(sub_objs.elms()==src.sub_objs.elms())
  335. {
  336. REPA(sub_objs)
  337. {
  338. C SubObj &obj=sub_objs[i], *src_obj=src.findSubObj(obj.id);
  339. if(!src_obj || !obj.equal(*src_obj))return false;
  340. }
  341. return true;
  342. }
  343. return false;
  344. }
  345. bool EditObject::subObjsNewer(C EditObject &src)C
  346. {
  347. REPA(sub_objs)
  348. {
  349. C SubObj &obj=sub_objs[i], *src_obj=src.findSubObj(obj.id);
  350. if(!src_obj || obj.newer(*src_obj))return true;
  351. }
  352. return false;
  353. }
  354. bool EditObject::old(C TimeStamp &now)C {return base_time< now && access_time< now && type_time< now && editor_type_time< now && const_time< now && path_time< now && mesh_variation_time< now && ::EditParams::old (now) && subObjsOld (now);}
  355. bool EditObject::equal(C EditObject &src )C {return base_time==src.base_time && access_time==src.access_time && type_time==src.type_time && editor_type_time==src.editor_type_time && const_time==src.const_time && path_time==src.path_time && mesh_variation_time==src.mesh_variation_time && ::EditParams::equal(src) && subObjsEqual(src);}
  356. bool EditObject::newer(C EditObject &src )C {return base_time> src.base_time || access_time> src.access_time || type_time> src.type_time || editor_type_time> src.editor_type_time || const_time> src.const_time || path_time> src.path_time || mesh_variation_time> src.mesh_variation_time || ::EditParams::newer(src) || subObjsNewer(src);}
  357. void EditObject::newData()
  358. {
  359. base_time++; access_time++; type_time++; const_time++; path_time++; mesh_variation_time++;
  360. //editor_type_time++; don't set this
  361. }
  362. void EditObject::create(C EditObject &src)
  363. {
  364. ::EditParams::create(src);
  365. flag =src.flag ; const_time=src. const_time;
  366. access =src.access ; access_time=src. access_time;
  367. path =src.path ; path_time=src. path_time;
  368. type =src.type ; type_time=src. type_time;
  369. base =src.base ; base_time=src. base_time;
  370. mesh_variation_id=src.mesh_variation_id; mesh_variation_time=src.mesh_variation_time;
  371. editor_type=src.editor_type;
  372. }
  373. void EditObject::create(C Object &src, C UID &type, C EditObjectPtr &base, C TimeStamp &time)
  374. {
  375. ::EditParams::create(src, time);
  376. base_time=access_time=type_time=const_time=path_time=mesh_variation_time=time;
  377. FlagSet(flag, OVR_ACCESS , src.customAccess ());
  378. FlagSet(flag, OVR_TYPE , src.customType ());
  379. FlagSet(flag, OVR_PATH , src.customPath ());
  380. FlagSet(flag, OVR_CONST , src.customConstant ());
  381. FlagSet(flag, OVR_MESH_VARIATION, src.customMeshVariation());
  382. FlagSet(flag, CONSTANT , src.constant ());
  383. access =src.access ();
  384. path =src.path ();
  385. mesh_variation_id=src.meshVariationID();
  386. T.type=type;
  387. T.base=base;
  388. editor_type.zero();
  389. editor_type_time.zero(); // set this to zero because depending on this we're detecting if it was manually set
  390. }
  391. void EditObject::copyTo(Object &obj, C Project &proj, bool zero_align, C UID *mesh_id, C UID *phys_id)C // 'zero_align' should be set only to ELM_OBJ
  392. {
  393. ::EditParams::copyTo(obj);
  394. obj.access (FlagTest(flag, OVR_ACCESS ), access );
  395. obj.type (FlagTest(flag, OVR_TYPE ), type );
  396. obj.constant (FlagTest(flag, OVR_CONST ), constant() );
  397. obj.path (FlagTest(flag, OVR_PATH ), path );
  398. obj.meshVariationID(FlagTest(flag, OVR_MESH_VARIATION), mesh_variation_id);
  399. obj.align (zero_align);
  400. UID base_id=base.id(); obj.base( proj.gamePath( base_id));
  401. if(!mesh_id)obj.mesh(false);else obj.mesh(true, proj.gamePath(*mesh_id));
  402. if(!phys_id)obj.phys(false);else obj.phys(true, proj.gamePath(*phys_id));
  403. FREPA(sub_objs){C SubObj &src=sub_objs[i]; if(!src.removed)obj.sub_objs.New().base(proj.gamePath(src.elm_obj_id));}
  404. }
  405. void EditObject::copyTo(Edit::ObjData &obj, bool include_removed_params)C
  406. {
  407. obj.elm_obj_class_id=type;
  408. obj. access=access;
  409. obj. path=path;
  410. obj.params.clear();
  411. Memt<C EditObject*> bases;
  412. bool inherited=false;
  413. for(C EditObject *cur=this; cur && bases.include(cur); cur=cur->base(), inherited=true) // start from self, go to base/parents
  414. FREPA(*cur) // list in order
  415. {
  416. C EditParam &s=(*cur)[i];
  417. if(include_removed_params || !s.removed)
  418. {
  419. Edit::ObjData::Param &d=obj.params.New();
  420. SCAST(EE::Param, d)=s;
  421. d.id =s.id;
  422. d.removed =s.removed;
  423. d.inherited=inherited;
  424. }
  425. }
  426. }
  427. void EditObject::updateEditorType(cchar *edit_path)
  428. {
  429. if(!editor_type_time.is()) // if this is not a manually set value (this can occur only for OBJ_CLASS), this check is important because we can't adjust the 'editor_type' of OBJ_CLASS in this method
  430. {
  431. if(base) // if we have a base
  432. {
  433. if(FlagTest(flag, OVR_TYPE)) // we must get 'editor_type' from custom 'type' (check this only inside 'base' condition, because this will mean that it's a world object, and only then we're interested in 'OVR_TYPE', because otherwise 'OVR_TYPE' is set only for 'OBJ_CLASS' for which we can't adjust 'editor_type')
  434. {
  435. EditObjectPtr type_base; if(type.valid())type_base=Str(edit_path).tailSlash(true)+EncodeFileName(type);
  436. if(type_base)editor_type=type_base->editor_type;else editor_type.zero();
  437. }else
  438. editor_type=base->editor_type;
  439. }else editor_type.zero();
  440. }
  441. }
  442. void EditObject::updateBase(cchar *edit_path)
  443. {
  444. if(!FlagTest(flag, OVR_ACCESS ))access=(base ? base->access : OBJ_ACCESS_TERRAIN);
  445. if(!FlagTest(flag, OVR_TYPE ))if(base)type=base->type;else type.zero();
  446. if(!FlagTest(flag, OVR_CONST ))FlagSet(flag, CONSTANT, base ? base->constant() : false);
  447. if(!FlagTest(flag, OVR_PATH ))path=(base ? base->path : OBJ_PATH_CREATE);
  448. if(!FlagTest(flag, OVR_MESH_VARIATION))mesh_variation_id=(base ? base->mesh_variation_id : 0);
  449. updateEditorType(edit_path);
  450. }
  451. bool EditObject::newParam(C Str &name, PARAM_TYPE type, C Project &proj)
  452. {
  453. EditObjectPtr obj_class; // need to keep ptr here because we're storing pointer to its parameter in 'base_param'
  454. C EditParam *base_param=baseFindParam(name, type);
  455. if(!base_param && (flag&OVR_TYPE))
  456. if(obj_class=proj.editPath(T.type))
  457. base_param=obj_class->EditParams::findParam(name, type);
  458. if(base_param)
  459. {
  460. EditParam *dest=EditParams::findParam(base_param->id); // find existing param with same id
  461. if(!dest){dest=&New(); dest->id=base_param->id;}else if(dest->removed)dest->setRemoved(false);else return false; // if doesn't exist then create new and set id, if removed then un-remove, if exists then continue and don't override its value (this can happen if we're overriding value for multiple objects and some of which have this value already and some don't)
  462. SCAST(Param, *dest)=*base_param; dest->nameTypeValueUTC(); // set values and update times
  463. return true;
  464. }
  465. return false;
  466. }
  467. bool EditObject::sync(C EditObject &src, cchar *edit_path)
  468. {
  469. bool changed=::EditParams::sync(src);
  470. changed|=Sync( base_time, src. base_time, base , src.base );
  471. changed|=Sync(editor_type_time, src.editor_type_time, editor_type, src.editor_type);
  472. if(Sync(access_time, src.access_time))
  473. {
  474. changed=true;
  475. access=src.access;
  476. FlagSet(flag, OVR_ACCESS, FlagTest(src.flag, OVR_ACCESS));
  477. }
  478. if(Sync(type_time, src.type_time))
  479. {
  480. changed=true;
  481. type=src.type;
  482. FlagSet(flag, OVR_TYPE, FlagTest(src.flag, OVR_TYPE));
  483. }
  484. if(Sync(const_time, src.const_time))
  485. {
  486. changed=true;
  487. FlagSet(flag, CONSTANT , src.constant());
  488. FlagSet(flag, OVR_CONST, FlagTest(src.flag, OVR_CONST));
  489. }
  490. if(Sync(path_time, src.path_time))
  491. {
  492. changed=true;
  493. path=src.path;
  494. FlagSet(flag, OVR_PATH, FlagTest(src.flag, OVR_PATH));
  495. }
  496. if(Sync(mesh_variation_time, src.mesh_variation_time))
  497. {
  498. changed=true;
  499. mesh_variation_id=src.mesh_variation_id;
  500. FlagSet(flag, OVR_MESH_VARIATION, FlagTest(src.flag, OVR_MESH_VARIATION));
  501. }
  502. REPA(src.sub_objs)
  503. {
  504. C SubObj &s=src.sub_objs[i];
  505. if(SubObj *dest=findSubObj(s.id))changed|=dest->sync(s);else{changed=true; sub_objs.add(s);}
  506. }
  507. if(changed)updateBase(edit_path);
  508. return changed;
  509. }
  510. bool EditObject::undo(C EditObject &src, cchar *edit_path)
  511. {
  512. bool changed=::EditParams::undo(src);
  513. changed|=Undo( base_time, src. base_time, base , src.base );
  514. changed|=Undo(editor_type_time, src.editor_type_time, editor_type, src.editor_type);
  515. if(Undo(access_time, src.access_time))
  516. {
  517. changed=true;
  518. access=src.access;
  519. FlagSet(flag, OVR_ACCESS, FlagTest(src.flag, OVR_ACCESS));
  520. }
  521. if(Undo(type_time, src.type_time))
  522. {
  523. changed=true;
  524. type=src.type;
  525. FlagSet(flag, OVR_TYPE, FlagTest(src.flag, OVR_TYPE));
  526. }
  527. if(Undo(const_time, src.const_time))
  528. {
  529. changed=true;
  530. FlagSet(flag, CONSTANT , src.constant());
  531. FlagSet(flag, OVR_CONST, FlagTest(src.flag, OVR_CONST));
  532. }
  533. if(Undo(path_time, src.path_time))
  534. {
  535. changed=true;
  536. path=src.path;
  537. FlagSet(flag, OVR_PATH, FlagTest(src.flag, OVR_PATH));
  538. }
  539. if(Undo(mesh_variation_time, src.mesh_variation_time))
  540. {
  541. changed=true;
  542. mesh_variation_id=src.mesh_variation_id;
  543. FlagSet(flag, OVR_MESH_VARIATION, FlagTest(src.flag, OVR_MESH_VARIATION));
  544. }
  545. // sub objects
  546. // mark as removed those that aren't present in 'src'
  547. REPA(sub_objs)
  548. {
  549. SubObj &s=sub_objs[i]; if(!s.removed && !src.findSubObj(s.id)){s.removed=true; s.removed_time++; changed=true;}
  550. }
  551. // undo/insert from 'src'
  552. REPA(src.sub_objs)
  553. {
  554. C SubObj &s=src.sub_objs[i];
  555. SubObj *t=findSubObj(s.id);
  556. if(t)changed|=t->undo(s);else{sub_objs.add(s); changed=true;}
  557. }
  558. if(changed)updateBase(edit_path);
  559. return changed;
  560. }
  561. bool EditObject::modify(C MemPtr<Edit::ObjChange> &changes, Project &proj)
  562. {
  563. bool changed=false;
  564. FREPA(changes) // process in order
  565. {
  566. C Edit::ObjChange &change=changes[i];
  567. switch(change.cmd)
  568. {
  569. case Edit::EI_OBJ_PARAM_REMOVE_ID:
  570. {
  571. if(EditParam *param=EditParams::findParam(change.id))
  572. if(!param->removed){changed=true; param->setRemoved(true);}
  573. }break;
  574. case Edit::EI_OBJ_PARAM_REMOVE_NAME:
  575. {
  576. if(EditParam *param=(InRange(change.type, PARAM_NUM) ? findParamInclRemoved(change.name, change.type) : findParamInclRemoved(change.name)))
  577. if(!param->removed){changed=true; param->setRemoved(true);}
  578. }break;
  579. case Edit::EI_OBJ_PARAM_RESTORE_ID:
  580. {
  581. if(EditParam *param=EditParams::findParam(change.id))
  582. if(param->removed){changed=true; param->setRemoved(false);}
  583. }break;
  584. case Edit::EI_OBJ_PARAM_RESTORE_NAME:
  585. {
  586. if(EditParam *param=(InRange(change.type, PARAM_NUM) ? findParamInclRemoved(change.name, change.type) : findParamInclRemoved(change.name)))
  587. if(param->removed){changed=true; param->setRemoved(false);}
  588. }break;
  589. case Edit::EI_OBJ_PARAM_RENAME_ID:
  590. {
  591. if(EditParam *param=EditParams::findParam(change.id))
  592. if(!Equal(param->name, change.param.name, true)){changed=true; param->setName(change.param.name);}
  593. }break;
  594. case Edit::EI_OBJ_PARAM_RENAME_NAME:
  595. {
  596. if(EditParam *param=(InRange(change.type, PARAM_NUM) ? findParamInclRemoved(change.name, change.type) : findParamInclRemoved(change.name)))
  597. if(!Equal(param->name, change.param.name, true)){changed=true; param->setName(change.param.name);}
  598. }break;
  599. case Edit::EI_OBJ_PARAM_SET_TYPE_VALUE_ID:
  600. {
  601. if(EditParam *param=EditParams::findParam(change.id))
  602. {
  603. if(CompareValue(*param, change.param)){changed=true; param->setTypeValue(change.param);} // set type value
  604. if(param->removed){changed=true; param->setRemoved(false);} // restore
  605. }
  606. }break;
  607. case Edit::EI_OBJ_PARAM_SET_TYPE_VALUE_NAME:
  608. {
  609. if(EditParam *param=(InRange(change.type, PARAM_NUM) ? findParamInclRemoved(change.name, change.type) : findParamInclRemoved(change.name)))
  610. {
  611. if(CompareValue(*param, change.param)){changed=true; param->setTypeValue(change.param);} // set type value
  612. if(param->removed){changed=true; param->setRemoved(false);} // restore
  613. }else // create new one
  614. {
  615. changed=true;
  616. PARAM_TYPE type=(InRange(change.type, PARAM_NUM) ? change.type : change.param.type); // if type is not specified then use target value type
  617. newParam(change.name, type, proj);
  618. if(EditParam *param=(InRange(change.type, PARAM_NUM) ? findParamInclRemoved(change.name, change.type) : findParamInclRemoved(change.name)))
  619. {
  620. param->setTypeValue(change.param); // set type value
  621. if(param->removed)param->setRemoved(false); // restore
  622. }else // create new one
  623. {
  624. New().create(change.param).name=change.name;
  625. }
  626. }
  627. }break;
  628. }
  629. }
  630. return changed;
  631. }
  632. bool EditObject::save(File &f, cchar *edit_path)C
  633. {
  634. f.cmpUIntV(2);
  635. ::EditParams::save(f, EditToGamePath(edit_path)); // 'EditParams' requires game path
  636. f<<flag<<base.id()<<editor_type;
  637. if(flag&OVR_ACCESS )f<<access;
  638. if(flag&OVR_TYPE )f<<type;
  639. if(flag&OVR_PATH )f<<path;
  640. if(flag&OVR_MESH_VARIATION)f<<mesh_variation_id;
  641. f<<base_time<<access_time<<type_time<<editor_type_time<<const_time<<path_time<<mesh_variation_time;
  642. Save(f, sub_objs);
  643. return f.ok();
  644. }
  645. bool EditObject::load(File &f, cchar *edit_path)
  646. {
  647. switch(f.decUIntV())
  648. {
  649. case 2:
  650. {
  651. if(!::EditParams::load(f, EditToGamePath(edit_path)))goto error; // 'EditParams' requires game path
  652. UID base_id;
  653. f>>flag>>base_id>>editor_type; if(base_id.valid())base=Str(edit_path).tailSlash(true)+EncodeFileName(base_id);else base=null;
  654. if( flag&OVR_ACCESS )f>>access ;else access =(base ? base->access : OBJ_ACCESS_TERRAIN);
  655. if( flag&OVR_TYPE )f>>type ;else if(base)type=base->type;else type.zero();
  656. if(!(flag&OVR_CONST) ) FlagSet(flag, CONSTANT, base ? base->constant() : false );
  657. if( flag&OVR_PATH )f>>path ;else path =(base ? base->path : OBJ_PATH_CREATE );
  658. if( flag&OVR_MESH_VARIATION)f>>mesh_variation_id;else mesh_variation_id=(base ? base->mesh_variation_id : 0 );
  659. f>>base_time>>access_time>>type_time>>editor_type_time>>const_time>>path_time>>mesh_variation_time;
  660. updateEditorType(edit_path);
  661. if(!Load(f, sub_objs))goto error;
  662. if(f.ok())return true;
  663. }break;
  664. case 1:
  665. {
  666. if(!::EditParams::load(f, EditToGamePath(edit_path)))goto error; // 'EditParams' requires game path
  667. UID base_id;
  668. f>>flag>>base_id>>editor_type; if(base_id.valid())base=Str(edit_path).tailSlash(true)+EncodeFileName(base_id);else base=null;
  669. if( flag&OVR_ACCESS)f>>access;else access=(base ? base->access : OBJ_ACCESS_TERRAIN);
  670. if( flag&OVR_TYPE )f>>type ;else if(base)type=base->type;else type.zero();
  671. if(!(flag&OVR_CONST))FlagSet(flag, CONSTANT, base ? base->constant() : false);
  672. if( flag&OVR_PATH )f>>path ;else path=(base ? base->path : OBJ_PATH_CREATE);
  673. f>>base_time>>access_time>>type_time>>editor_type_time>>const_time>>path_time;
  674. updateEditorType(edit_path);
  675. if(!Load(f, sub_objs))goto error;
  676. mesh_variation_id=0; mesh_variation_time=0;
  677. if(f.ok())return true;
  678. }break;
  679. case 0:
  680. {
  681. if(!::EditParams::load(f, EditToGamePath(edit_path)))goto error; // 'EditParams' requires game path
  682. UID base_id;
  683. f>>flag>>base_id>>editor_type; if(base_id.valid())base=Str(edit_path).tailSlash(true)+EncodeFileName(base_id);else base=null;
  684. if( flag&OVR_ACCESS)f>>access;else access=(base ? base->access : OBJ_ACCESS_TERRAIN);
  685. if( flag&OVR_TYPE )f>>type ;else if(base)type=base->type;else type.zero();
  686. if(!(flag&OVR_CONST))FlagSet(flag, CONSTANT, base ? base->constant() : false);
  687. if( flag&OVR_PATH )f>>path ;else path=(base ? base->path : OBJ_PATH_CREATE);
  688. f>>base_time>>access_time>>type_time>>editor_type_time>>const_time>>path_time;
  689. updateEditorType(edit_path);
  690. sub_objs.clear();
  691. mesh_variation_id=0; mesh_variation_time=0;
  692. if(f.ok())return true;
  693. }break;
  694. }
  695. error:
  696. del(); return false;
  697. }
  698. bool EditObject::load(C Str &name)
  699. {
  700. File f; if(f.readTry(name))return load(f, GetPath(name));
  701. del(); return false;
  702. }
  703. C Str & GuiEditParam::desc()C {return _desc;}
  704. GuiEditParam& GuiEditParam::desc(C Str &desc ) {_desc=desc; return T;}
  705. GuiEditParam& GuiEditParam::min(dbl min ) {min_use=true; min_value=min; return T;}
  706. GuiEditParam& GuiEditParam::max(dbl max ) {max_use=true; max_value=max; return T;}
  707. GuiEditParam& GuiEditParam::range(dbl min, dbl max) {return T.min(min).max(max);}
  708. GuiEditParam& GuiEditParam::mouseEditSpeed(flt speed) {mouse_edit_speed=speed; return T;}
  709. GuiEditParam& GuiEditParam::mouseEditMode(PROP_MOUSE_EDIT_MODE mode ) {mouse_edit_mode =mode ; return T;}
  710. EditParam::EditParam() : id(UID().randomizeValid()), removed(false) {}
  711. EditObject::EditObject() : flag(0), access(OBJ_ACCESS_TERRAIN), path(OBJ_PATH_CREATE), mesh_variation_id(0), type(UIDZero), editor_type(UIDZero) {}
  712. EditObject::SubObj::SubObj() : removed(false), id(UID().randomizeValid()), elm_obj_id(UIDZero) {}
  713. GuiEditParam::GuiEditParam() : priority(0), min_use(false), max_use(false), min_value(0 ), max_value(0 ), mouse_edit_speed(0), mouse_edit_mode(PROP_MOUSE_EDIT_LINEAR), enum_name(null) {}
  714. /******************************************************************************/