database.vala 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307
  1. /*
  2. * Copyright (c) 2012-2018 Daniele Bartolini and individual contributors.
  3. * License: https://github.com/dbartolini/crown/blob/master/LICENSE
  4. */
  5. using Gee;
  6. namespace Crown
  7. {
  8. public class Database
  9. {
  10. private enum Action
  11. {
  12. CREATE,
  13. DESTROY,
  14. SET_PROPERTY_NULL,
  15. SET_PROPERTY_BOOL,
  16. SET_PROPERTY_DOUBLE,
  17. SET_PROPERTY_STRING,
  18. SET_PROPERTY_GUID,
  19. SET_PROPERTY_VECTOR3,
  20. SET_PROPERTY_QUATERNION,
  21. ADD_TO_SET,
  22. REMOVE_FROM_SET,
  23. RESTORE_POINT
  24. }
  25. private struct RestorePoint
  26. {
  27. public int id;
  28. public uint32 size;
  29. public Guid[] data;
  30. }
  31. private class Stack
  32. {
  33. private uint8[] _data;
  34. private uint32 _read;
  35. public Stack()
  36. {
  37. _data = new uint8[1024*1024];
  38. _read = 0;
  39. }
  40. public void clear()
  41. {
  42. _read = 0;
  43. }
  44. public uint32 size()
  45. {
  46. return _read;
  47. }
  48. public void write_data(void* data, ulong len)
  49. {
  50. uint8* buf = (uint8*)data;
  51. for (ulong i = 0; i < len; ++i, ++_read)
  52. _data[_read] = buf[i];
  53. }
  54. public void write_bool(bool a)
  55. {
  56. write_data(&a, sizeof(bool));
  57. }
  58. public void write_int(int a)
  59. {
  60. write_data(&a, sizeof(int));
  61. }
  62. public void write_uint32(uint32 a)
  63. {
  64. write_data(&a, sizeof(uint32));
  65. }
  66. public void write_double(double a)
  67. {
  68. write_data(&a, sizeof(double));
  69. }
  70. public void write_string(string str)
  71. {
  72. uint32 len = str.length;
  73. write_data(&str.data[0], len);
  74. write_data(&len, sizeof(uint32));
  75. }
  76. public void write_guid(Guid a)
  77. {
  78. write_data(&a, sizeof(Guid));
  79. }
  80. public void write_vector3(Vector3 a)
  81. {
  82. write_data(&a, sizeof(Vector3));
  83. }
  84. public void write_quaternion(Quaternion a)
  85. {
  86. write_data(&a, sizeof(Quaternion));
  87. }
  88. public void write_action(Action t)
  89. {
  90. write_uint32((uint32)t);
  91. }
  92. public Action read_action()
  93. {
  94. _read -= (uint32)sizeof(uint32);
  95. uint32 a = *(uint32*)(&_data[_read]);
  96. return (Action)a;
  97. }
  98. public bool read_bool()
  99. {
  100. _read -= (uint32)sizeof(bool);
  101. bool a = *(bool*)(&_data[_read]);
  102. return a;
  103. }
  104. public int read_int()
  105. {
  106. _read -= (uint32)sizeof(int);
  107. int a = *(int*)(&_data[_read]);
  108. return a;
  109. }
  110. public uint32 read_uint32()
  111. {
  112. _read -= (uint32)sizeof(uint32);
  113. uint32 a = *(uint32*)(&_data[_read]);
  114. return a;
  115. }
  116. public double read_double()
  117. {
  118. _read -= (uint32)sizeof(double);
  119. double a = *(double*)(&_data[_read]);
  120. return a;
  121. }
  122. public Guid read_guid()
  123. {
  124. _read -= (uint32)sizeof(Guid);
  125. Guid a = *(Guid*)(&_data[_read]);
  126. return a;
  127. }
  128. public Vector3 read_vector3()
  129. {
  130. _read -= (uint32)sizeof(Vector3);
  131. Vector3 a = *(Vector3*)(&_data[_read]);
  132. return a;
  133. }
  134. public Quaternion read_quaternion()
  135. {
  136. _read -= (uint32)sizeof(Quaternion);
  137. Quaternion a = *(Quaternion*)(&_data[_read]);
  138. return a;
  139. }
  140. public string read_string()
  141. {
  142. _read -= (uint32)sizeof(uint32);
  143. uint32 len = *(uint32*)(&_data[_read]);
  144. _read -= len;
  145. uint8[] str = new uint8[len + 1];
  146. for (uint32 i = 0; i < len; ++i)
  147. str[i] = *(uint8*)(&_data[_read + i]);
  148. str[len] = '\0';
  149. return (string)str;
  150. }
  151. public void write_create_action(Guid id)
  152. {
  153. write_guid(id);
  154. write_action(Action.CREATE);
  155. }
  156. public void write_destroy_action(Guid id)
  157. {
  158. write_guid(id);
  159. write_action(Action.DESTROY);
  160. }
  161. public void write_set_property_null_action(Guid id, string key)
  162. {
  163. // No value to push
  164. write_string(key);
  165. write_guid(id);
  166. write_action(Action.SET_PROPERTY_NULL);
  167. }
  168. public void write_set_property_bool_action(Guid id, string key, bool val)
  169. {
  170. write_bool(val);
  171. write_string(key);
  172. write_guid(id);
  173. write_action(Action.SET_PROPERTY_BOOL);
  174. }
  175. public void write_set_property_double_action(Guid id, string key, double val)
  176. {
  177. write_double(val);
  178. write_string(key);
  179. write_guid(id);
  180. write_action(Action.SET_PROPERTY_DOUBLE);
  181. }
  182. public void write_set_property_string_action(Guid id, string key, string val)
  183. {
  184. write_string(val);
  185. write_string(key);
  186. write_guid(id);
  187. write_action(Action.SET_PROPERTY_STRING);
  188. }
  189. public void write_set_property_guid_action(Guid id, string key, Guid val)
  190. {
  191. write_guid(val);
  192. write_string(key);
  193. write_guid(id);
  194. write_action(Action.SET_PROPERTY_GUID);
  195. }
  196. public void write_set_property_vector3_action(Guid id, string key, Vector3 val)
  197. {
  198. write_vector3(val);
  199. write_string(key);
  200. write_guid(id);
  201. write_action(Action.SET_PROPERTY_VECTOR3);
  202. }
  203. public void write_set_property_quaternion_action(Guid id, string key, Quaternion val)
  204. {
  205. write_quaternion(val);
  206. write_string(key);
  207. write_guid(id);
  208. write_action(Action.SET_PROPERTY_QUATERNION);
  209. }
  210. public void write_add_to_set_action(Guid id, string key, Guid item_id)
  211. {
  212. write_guid(item_id);
  213. write_string(key);
  214. write_guid(id);
  215. write_action(Action.ADD_TO_SET);
  216. }
  217. public void write_remove_from_set_action(Guid id, string key, Guid item_id)
  218. {
  219. write_guid(item_id);
  220. write_string(key);
  221. write_guid(id);
  222. write_action(Action.REMOVE_FROM_SET);
  223. }
  224. public void write_restore_point(int id, uint32 size, Guid[] data)
  225. {
  226. uint32 num_guids = data.length;
  227. for (uint32 i = 0; i < num_guids; ++i)
  228. write_guid(data[i]);
  229. write_uint32(num_guids);
  230. write_uint32(size);
  231. write_int(id);
  232. write_action(Action.RESTORE_POINT);
  233. }
  234. public uint32 peek_type()
  235. {
  236. return *(uint32*)(&_data[_read - (uint32)sizeof(uint32)]);
  237. }
  238. public RestorePoint read_restore_point()
  239. {
  240. Action t = read_action();
  241. assert(t == Action.RESTORE_POINT);
  242. int id = read_int();
  243. uint32 size = read_uint32();
  244. uint32 num_guids = read_uint32();
  245. Guid[] ids = new Guid[num_guids];
  246. for (uint32 i = 0; i < num_guids; ++i)
  247. ids[i] = read_guid();
  248. return { id, size, ids };
  249. }
  250. }
  251. // Data
  252. private HashMap<string, Value?> _data;
  253. private Stack _undo;
  254. private Stack _redo;
  255. private Stack _undo_points;
  256. private Stack _redo_points;
  257. private bool _changed;
  258. // Signals
  259. public signal void key_changed(Guid id, string key);
  260. public signal void undo_redo(bool undo, int id, Guid[] data);
  261. public Database()
  262. {
  263. _data = new HashMap<string, Value?>();
  264. _undo = new Stack();
  265. _redo = new Stack();
  266. _undo_points = new Stack();
  267. _redo_points = new Stack();
  268. reset();
  269. }
  270. /// Resets database to clean state.
  271. public void reset()
  272. {
  273. _data.clear();
  274. _undo.clear();
  275. _redo.clear();
  276. _undo_points.clear();
  277. _redo_points.clear();
  278. _changed = false;
  279. // This is a special field which stores all objects
  280. _data.set("_objects", new HashMap<string, Value?>());
  281. }
  282. /// Returns whether the database has been changed since last call to Save().
  283. public bool changed()
  284. {
  285. return _changed;
  286. }
  287. /// Saves database to path without marking it as not changed.
  288. public void dump(string path)
  289. {
  290. Hashtable json = encode();
  291. SJSON.save(json, path);
  292. }
  293. /// Saves database to path.
  294. public void save(string path)
  295. {
  296. dump(path);
  297. _changed = false;
  298. }
  299. /// Loads database from path.
  300. public void load(string path)
  301. {
  302. Hashtable json = SJSON.load(path);
  303. decode(json);
  304. _changed = false;
  305. }
  306. private Hashtable encode()
  307. {
  308. return encode_object(GUID_ZERO, _data);
  309. }
  310. private static bool is_valid_value(Value? value)
  311. {
  312. return value == null
  313. || value.holds(typeof(bool))
  314. || value.holds(typeof(double))
  315. || value.holds(typeof(string))
  316. || value.holds(typeof(Guid))
  317. || value.holds(typeof(Vector3))
  318. || value.holds(typeof(Quaternion))
  319. ;
  320. }
  321. private static bool is_valid_key(string key)
  322. {
  323. return key.length > 0
  324. && key != "_objects"
  325. && !key.has_prefix(".")
  326. && !key.has_suffix(".")
  327. ;
  328. }
  329. #if 0
  330. private static string value_to_string(Value? value)
  331. {
  332. if (value == null)
  333. return "null";
  334. if (value.holds(typeof(bool)))
  335. return ((bool)value).to_string();
  336. if (value.holds(typeof(double)))
  337. return ((double)value).to_string();
  338. if (value.holds(typeof(string)))
  339. return ((string)value).to_string();
  340. if (value.holds(typeof(Guid)))
  341. return ((Guid)value).to_string();
  342. if (value.holds(typeof(Vector3)))
  343. return ((Vector3)value).to_string();
  344. if (value.holds(typeof(Quaternion)))
  345. return ((Quaternion)value).to_string();
  346. if (value.holds(typeof(HashSet)))
  347. return "Set<Guid>";
  348. return "<invalid>";
  349. }
  350. #endif // CROWN_DEBUG
  351. public void decode(Hashtable json)
  352. {
  353. reset();
  354. decode_object(GUID_ZERO, "", json);
  355. }
  356. private void decode_object(Guid id, string db_key, Hashtable json)
  357. {
  358. string old_db = db_key;
  359. string k = db_key;
  360. string[] keys = json.keys.to_array();
  361. foreach (string key in keys)
  362. {
  363. assert(key != "_objects");
  364. if (key == "id")
  365. continue;
  366. Value? val = json[key];
  367. k += k == "" ? key : ("." + key);
  368. if (val.holds(typeof(Hashtable)))
  369. {
  370. Hashtable ht = (Hashtable)val;
  371. decode_object(id, k, ht);
  372. }
  373. else if (val.holds(typeof(ArrayList)))
  374. {
  375. ArrayList<Value?> arr = (ArrayList<Value?>)val;
  376. if (arr.size > 0 && arr[0].holds(typeof(double)))
  377. set_property_internal(id, k, decode_value(val));
  378. else
  379. decode_set(id, key, arr);
  380. }
  381. else
  382. {
  383. set_property_internal(id, k, decode_value(val));
  384. }
  385. k = old_db;
  386. }
  387. }
  388. private void decode_set(Guid id, string key, ArrayList<Value?> json)
  389. {
  390. // Set should be created even if it is empty.
  391. create_empty_set(id, key);
  392. for (int i = 0; i < json.size; ++i)
  393. {
  394. Hashtable obj = (Hashtable)json[i];
  395. Guid item_id = Guid.parse((string)obj["id"]);
  396. create_internal(item_id);
  397. decode_object(item_id, "", obj);
  398. add_to_set_internal(id, key, item_id);
  399. }
  400. }
  401. private Value? decode_value(Value? value)
  402. {
  403. if (value.holds(typeof(ArrayList)))
  404. {
  405. ArrayList<Value?> al = (ArrayList<Value?>)value;
  406. if (al.size == 3)
  407. return Vector3((double)al[0], (double)al[1], (double)al[2]);
  408. else if (al.size == 4)
  409. return Quaternion((double)al[0], (double)al[1], (double)al[2], (double)al[3]);
  410. else
  411. assert(false);
  412. }
  413. else if (value.holds(typeof(string)))
  414. {
  415. Guid id;
  416. if (Guid.try_parse((string)value, out id))
  417. return id;
  418. return value;
  419. }
  420. else if (value == null || value.holds(typeof(bool)) || value.holds(typeof(double)))
  421. {
  422. return value;
  423. }
  424. else
  425. {
  426. assert(false);
  427. }
  428. return null;
  429. }
  430. private Hashtable encode_object(Guid id, HashMap<string, Value?> db)
  431. {
  432. Hashtable obj = new Hashtable();
  433. if (id != GUID_ZERO)
  434. obj["id"] = id.to_string();
  435. string[] keys = db.keys.to_array();
  436. foreach (string key in keys)
  437. {
  438. if (key == "_objects")
  439. continue;
  440. string[] foo = key.split(".");
  441. Hashtable x = obj;
  442. if (foo.length > 1)
  443. {
  444. for (int i = 0; i < foo.length - 1; ++i)
  445. {
  446. string f = foo[i];
  447. if (x.has_key(f))
  448. {
  449. x = (Hashtable)x[f];
  450. continue;
  451. }
  452. Hashtable y = new Hashtable();
  453. x.set(f, y);
  454. x = y;
  455. }
  456. }
  457. x.set(foo[foo.length-1], encode_value(db[key]));
  458. }
  459. return obj;
  460. }
  461. private Value? encode_value(Value? value)
  462. {
  463. assert(is_valid_value(value) || value.holds(typeof(HashSet)));
  464. if (value.holds(typeof(Vector3)))
  465. {
  466. Vector3 v = (Vector3)value;
  467. ArrayList<Value?> arr = new Gee.ArrayList<Value?>();
  468. arr.add(v.x);
  469. arr.add(v.y);
  470. arr.add(v.z);
  471. return arr;
  472. }
  473. else if (value.holds(typeof(Quaternion)))
  474. {
  475. Quaternion q = (Quaternion)value;
  476. ArrayList<Value?> arr = new Gee.ArrayList<Value?>();
  477. arr.add(q.x);
  478. arr.add(q.y);
  479. arr.add(q.z);
  480. arr.add(q.w);
  481. return arr;
  482. }
  483. else if (value.holds(typeof(Guid)))
  484. {
  485. Guid id = (Guid)value;
  486. return id.to_string();
  487. }
  488. else if (value.holds(typeof(HashSet)))
  489. {
  490. HashSet<Guid?> hs = (HashSet<Guid?>)value;
  491. ArrayList<Value?> arr = new Gee.ArrayList<Value?>();
  492. foreach (Guid id in hs)
  493. {
  494. HashMap<string, Value?> objs = (HashMap<string, Value?>)_data["_objects"];
  495. arr.add(encode_object(id, (HashMap<string, Value?>)objs[id.to_string()]));
  496. }
  497. return arr;
  498. }
  499. else
  500. {
  501. return value;
  502. }
  503. }
  504. private HashMap<string, Value?> get_data(Guid id)
  505. {
  506. assert(has_object(id));
  507. return (HashMap<string, Value?>)(id == GUID_ZERO ? _data : (_data["_objects"] as HashMap<string, Value?>)[id.to_string()]);
  508. }
  509. private void create_internal(Guid id)
  510. {
  511. assert(id != GUID_ZERO);
  512. #if 0
  513. stdout.printf("create %s\n", id.to_string());
  514. #endif // CROWN_DEBUG
  515. (_data["_objects"] as HashMap<string, Value?>).set(id.to_string(), new HashMap<string, Value?>());
  516. _changed = true;
  517. key_changed(id, "_objects");
  518. }
  519. private void destroy_internal(Guid id)
  520. {
  521. assert(id != GUID_ZERO);
  522. assert(has_object(id));
  523. #if 0
  524. stdout.printf("destroy %s\n", id.to_string());
  525. #endif // CROWN_DEBUG
  526. (_data["_objects"] as HashMap<string, Value?>).unset(id.to_string());
  527. _changed = true;
  528. key_changed(id, "_objects");
  529. }
  530. private void set_property_internal(Guid id, string key, Value? value)
  531. {
  532. assert(has_object(id));
  533. assert(is_valid_key(key));
  534. assert(is_valid_value(value));
  535. #if 0
  536. stdout.printf("set_property %s %s %s\n"
  537. , id.to_string()
  538. , key
  539. , (value == null) ? "null" : value_to_string(value)
  540. );
  541. #endif // CROWN_DEBUG
  542. HashMap<string, Value?> ob = get_data(id);
  543. ob[key] = value;
  544. _changed = true;
  545. key_changed(id, key);
  546. }
  547. private void create_empty_set(Guid id, string key)
  548. {
  549. assert(has_object(id));
  550. assert(is_valid_key(key));
  551. HashMap<string, Value?> ob = get_data(id);
  552. assert(!ob.has_key(key));
  553. ob[key] = new HashSet<Guid?>(Guid.hash_func, Guid.equal_func);
  554. }
  555. private void add_to_set_internal(Guid id, string key, Guid item_id)
  556. {
  557. assert(has_object(id));
  558. assert(is_valid_key(key));
  559. assert(item_id != GUID_ZERO);
  560. assert(has_object(item_id));
  561. #if 0
  562. stdout.printf("add_to_set %s %s %s\n"
  563. , id.to_string()
  564. , key
  565. , item_id.to_string()
  566. );
  567. #endif // CROWN_DEBUG
  568. HashMap<string, Value?> ob = get_data(id);
  569. if (!ob.has_key(key))
  570. {
  571. HashSet<Guid?> hs = new HashSet<Guid?>(Guid.hash_func, Guid.equal_func);
  572. hs.add(item_id);
  573. ob[key] = hs;
  574. }
  575. else
  576. {
  577. (ob[key] as HashSet<Guid?>).add(item_id);
  578. }
  579. _changed = true;
  580. key_changed(id, key);
  581. }
  582. private void remove_from_set_internal(Guid id, string key, Guid item_id)
  583. {
  584. assert(has_object(id));
  585. assert(is_valid_key(key));
  586. assert(item_id != GUID_ZERO);
  587. #if 0
  588. stdout.printf("remove_from_set %s %s %s\n"
  589. , id.to_string()
  590. , key
  591. , item_id.to_string()
  592. );
  593. #endif // CROWN_DEBUG
  594. HashMap<string, Value?> ob = get_data(id);
  595. (ob[key] as HashSet<Guid?>).remove(item_id);
  596. _changed = true;
  597. key_changed(id, key);
  598. }
  599. public void create(Guid id)
  600. {
  601. assert(id != GUID_ZERO);
  602. assert(!has_object(id));
  603. _undo.write_destroy_action(id);
  604. _redo.clear();
  605. _redo_points.clear();
  606. create_internal(id);
  607. }
  608. public void destroy(Guid id)
  609. {
  610. assert(id != GUID_ZERO);
  611. assert(has_object(id));
  612. HashMap<string, Value?> o = get_data(id);
  613. string[] keys = o.keys.to_array();
  614. foreach (string key in keys)
  615. {
  616. Value? value = o[key];
  617. if (value.holds(typeof(HashSet)))
  618. {
  619. HashSet<Guid?> hs = (HashSet<Guid?>)value;
  620. Guid?[] ids = hs.to_array();
  621. foreach (Guid item_id in ids)
  622. {
  623. remove_from_set(id, key, item_id);
  624. destroy(item_id);
  625. }
  626. }
  627. else
  628. {
  629. set_property_null(id, key);
  630. }
  631. }
  632. _undo.write_create_action(id);
  633. _redo.clear();
  634. _redo_points.clear();
  635. destroy_internal(id);
  636. }
  637. public void set_property_null(Guid id, string key)
  638. {
  639. assert(has_object(id));
  640. assert(is_valid_key(key));
  641. assert(is_valid_value(null));
  642. HashMap<string, Value?> ob = get_data(id);
  643. if (ob.has_key(key) && ob[key] != null)
  644. {
  645. if (ob[key].holds(typeof(bool)))
  646. _undo.write_set_property_bool_action(id, key, (bool)ob[key]);
  647. if (ob[key].holds(typeof(double)))
  648. _undo.write_set_property_double_action(id, key, (double)ob[key]);
  649. if (ob[key].holds(typeof(string)))
  650. _undo.write_set_property_string_action(id, key, (string)ob[key]);
  651. if (ob[key].holds(typeof(Guid)))
  652. _undo.write_set_property_guid_action(id, key, (Guid)ob[key]);
  653. if (ob[key].holds(typeof(Vector3)))
  654. _undo.write_set_property_vector3_action(id, key, (Vector3)ob[key]);
  655. if (ob[key].holds(typeof(Quaternion)))
  656. _undo.write_set_property_quaternion_action(id, key, (Quaternion)ob[key]);
  657. }
  658. else
  659. {
  660. _undo.write_set_property_null_action(id, key);
  661. }
  662. _redo.clear();
  663. _redo_points.clear();
  664. set_property_internal(id, key, null);
  665. }
  666. public void set_property_bool(Guid id, string key, bool val)
  667. {
  668. assert(has_object(id));
  669. assert(is_valid_key(key));
  670. assert(is_valid_value(val));
  671. HashMap<string, Value?> ob = get_data(id);
  672. if (ob.has_key(key) && ob[key] != null)
  673. _undo.write_set_property_bool_action(id, key, (bool)ob[key]);
  674. else
  675. _undo.write_set_property_null_action(id, key);
  676. _redo.clear();
  677. _redo_points.clear();
  678. set_property_internal(id, key, val);
  679. }
  680. public void set_property_double(Guid id, string key, double val)
  681. {
  682. assert(has_object(id));
  683. assert(is_valid_key(key));
  684. assert(is_valid_value(val));
  685. HashMap<string, Value?> ob = get_data(id);
  686. if (ob.has_key(key) && ob[key] != null)
  687. _undo.write_set_property_double_action(id, key, (double)ob[key]);
  688. else
  689. _undo.write_set_property_null_action(id, key);
  690. _redo.clear();
  691. _redo_points.clear();
  692. set_property_internal(id, key, val);
  693. }
  694. public void set_property_string(Guid id, string key, string val)
  695. {
  696. assert(has_object(id));
  697. assert(is_valid_key(key));
  698. assert(is_valid_value(val));
  699. HashMap<string, Value?> ob = get_data(id);
  700. if (ob.has_key(key) && ob[key] != null)
  701. _undo.write_set_property_string_action(id, key, (string)ob[key]);
  702. else
  703. _undo.write_set_property_null_action(id, key);
  704. _redo.clear();
  705. _redo_points.clear();
  706. set_property_internal(id, key, val);
  707. }
  708. public void set_property_guid(Guid id, string key, Guid val)
  709. {
  710. assert(has_object(id));
  711. assert(is_valid_key(key));
  712. assert(is_valid_value(val));
  713. HashMap<string, Value?> ob = get_data(id);
  714. if (ob.has_key(key) && ob[key] != null)
  715. _undo.write_set_property_guid_action(id, key, (Guid)ob[key]);
  716. else
  717. _undo.write_set_property_null_action(id, key);
  718. _redo.clear();
  719. _redo_points.clear();
  720. set_property_internal(id, key, val);
  721. }
  722. public void set_property_vector3(Guid id, string key, Vector3 val)
  723. {
  724. assert(has_object(id));
  725. assert(is_valid_key(key));
  726. assert(is_valid_value(val));
  727. HashMap<string, Value?> ob = get_data(id);
  728. if (ob.has_key(key) && ob[key] != null)
  729. _undo.write_set_property_vector3_action(id, key, (Vector3)ob[key]);
  730. else
  731. _undo.write_set_property_null_action(id, key);
  732. _redo.clear();
  733. _redo_points.clear();
  734. set_property_internal(id, key, val);
  735. }
  736. public void set_property_quaternion(Guid id, string key, Quaternion val)
  737. {
  738. assert(has_object(id));
  739. assert(is_valid_key(key));
  740. assert(is_valid_value(val));
  741. HashMap<string, Value?> ob = get_data(id);
  742. if (ob.has_key(key) && ob[key] != null)
  743. _undo.write_set_property_quaternion_action(id, key, (Quaternion)ob[key]);
  744. else
  745. _undo.write_set_property_null_action(id, key);
  746. _redo.clear();
  747. _redo_points.clear();
  748. set_property_internal(id, key, val);
  749. }
  750. public void add_to_set(Guid id, string key, Guid item_id)
  751. {
  752. assert(has_object(id));
  753. assert(is_valid_key(key));
  754. assert(item_id != GUID_ZERO);
  755. assert(has_object(item_id));
  756. _undo.write_remove_from_set_action(id, key, item_id);
  757. _redo.clear();
  758. _redo_points.clear();
  759. add_to_set_internal(id, key, item_id);
  760. }
  761. public void remove_from_set(Guid id, string key, Guid item_id)
  762. {
  763. assert(has_object(id));
  764. assert(is_valid_key(key));
  765. assert(item_id != GUID_ZERO);
  766. _undo.write_add_to_set_action(id, key, item_id);
  767. _redo.clear();
  768. _redo_points.clear();
  769. remove_from_set_internal(id, key, item_id);
  770. }
  771. public bool has_object(Guid id)
  772. {
  773. bool contains = (_data["_objects"] as HashMap<string, Value?>).has_key(id.to_string());
  774. return id == GUID_ZERO || contains;
  775. }
  776. public bool has_property(Guid id, string key)
  777. {
  778. assert(has_object(id));
  779. assert(is_valid_key(key));
  780. return get_data(id).has_key(key);
  781. }
  782. public Value? get_property(Guid id, string key)
  783. {
  784. assert(has_object(id));
  785. assert(is_valid_key(key));
  786. HashMap<string, Value?> ob = get_data(id);
  787. Value? value = (ob.has_key(key) ? ob[key] : null);
  788. #if 0
  789. stdout.printf("get_property %s %s %s\n"
  790. , id.to_string()
  791. , key
  792. , (value == null) ? "null" : value_to_string(value)
  793. );
  794. #endif // CROWN_DEBUG
  795. return value;
  796. }
  797. public bool get_property_bool(Guid id, string key)
  798. {
  799. return (bool)get_property(id, key);
  800. }
  801. public double get_property_double(Guid id, string key)
  802. {
  803. return (double)get_property(id, key);
  804. }
  805. public string get_property_string(Guid id, string key)
  806. {
  807. return (string)get_property(id, key);
  808. }
  809. public Guid get_property_guid(Guid id, string key)
  810. {
  811. return (Guid)get_property(id, key);
  812. }
  813. public Vector3 get_property_vector3(Guid id, string key)
  814. {
  815. return (Vector3)get_property(id, key);
  816. }
  817. public Quaternion get_property_quaternion(Guid id, string key)
  818. {
  819. return (Quaternion)get_property(id, key);
  820. }
  821. public HashSet<Guid?> get_property_set(Guid id, string key, HashSet<Guid?> deffault)
  822. {
  823. assert(has_object(id));
  824. assert(is_valid_key(key));
  825. HashMap<string, Value?> ob = get_data(id);
  826. if (ob.has_key(key))
  827. return ob[key] as HashSet<Guid?>;
  828. else
  829. return deffault;
  830. #if 0
  831. // stdout.printf("get_property %s %s %s\n"
  832. // , id.to_string()
  833. // , key
  834. // , (value == null) ? "null" : value_to_string(value)
  835. // );
  836. #endif // CROWN_DEBUG
  837. }
  838. public HashMap<string, Value?> get_object(Guid id)
  839. {
  840. return (HashMap<string, Value?>)get_data(GUID_ZERO)[id.to_string()];
  841. }
  842. public string[] get_keys(Guid id)
  843. {
  844. HashMap<string, Value?> data = get_data(id);
  845. return data.keys.to_array();
  846. }
  847. public void add_restore_point(int id, Guid[] data)
  848. {
  849. #if 0
  850. stdout.printf("add_restore_point %d, undo size = %u\n", id, _undo.size());
  851. #endif // CROWN_DEBUG
  852. _undo_points.write_restore_point(id, _undo.size(), data);
  853. _redo.clear();
  854. _redo_points.clear();
  855. }
  856. /// Duplicates the object specified by id and assign new_id to the duplicated object.
  857. public void duplicate(Guid id, Guid new_id)
  858. {
  859. assert(id != GUID_ZERO);
  860. assert(new_id != GUID_ZERO);
  861. assert(id != new_id);
  862. assert(has_object(id));
  863. create(new_id);
  864. HashMap<string, Value?> ob = get_data(id);
  865. string[] keys = ob.keys.to_array();
  866. foreach (string key in keys)
  867. {
  868. Value? val = ob[key];
  869. if (val.holds(typeof(HashSet)))
  870. {
  871. HashSet<Guid?> hs = (HashSet<Guid?>)val;
  872. foreach (Guid j in hs)
  873. {
  874. Guid x = Guid.new_guid();
  875. duplicate(j, x);
  876. add_to_set(new_id, key, x);
  877. }
  878. }
  879. else
  880. {
  881. if (ob[key] == null)
  882. set_property_null(new_id, key);
  883. if (ob[key].holds(typeof(bool)))
  884. set_property_bool(new_id, key, (bool)ob[key]);
  885. if (ob[key].holds(typeof(double)))
  886. set_property_double(new_id, key, (double)ob[key]);
  887. if (ob[key].holds(typeof(string)))
  888. set_property_string(new_id, key, (string)ob[key]);
  889. if (ob[key].holds(typeof(Guid)))
  890. set_property_guid(new_id, key, (Guid)ob[key]);
  891. if (ob[key].holds(typeof(Vector3)))
  892. set_property_vector3(new_id, key, (Vector3)ob[key]);
  893. if (ob[key].holds(typeof(Quaternion)))
  894. set_property_quaternion(new_id, key, (Quaternion)ob[key]);
  895. }
  896. }
  897. }
  898. /// Copies the database to db under the given new_key.
  899. public void copy_to(Database db, string new_key)
  900. {
  901. assert(db != null);
  902. assert(is_valid_key(new_key));
  903. copy_deep(db, GUID_ZERO, new_key);
  904. }
  905. public void copy_deep(Database db, Guid id, string new_key)
  906. {
  907. HashMap<string, Value?> ob = get_data(id);
  908. string[] keys = ob.keys.to_array();
  909. foreach (string key in keys)
  910. {
  911. if (key == "_objects")
  912. continue;
  913. Value? value = ob[key];
  914. if (value.holds(typeof(HashSet)))
  915. {
  916. HashSet<Guid?> hs = (HashSet<Guid?>)value;
  917. foreach (Guid j in hs)
  918. {
  919. db.create(j);
  920. copy_deep(db, j, "");
  921. db.add_to_set(id, new_key + (new_key == "" ? "" : ".") + key, j);
  922. }
  923. }
  924. else
  925. {
  926. string kk = new_key + (new_key == "" ? "" : ".") + key;
  927. if (ob[key] == null)
  928. db.set_property_null(id, kk);
  929. if (ob[key].holds(typeof(bool)))
  930. db.set_property_bool(id, kk, (bool)ob[key]);
  931. if (ob[key].holds(typeof(double)))
  932. db.set_property_double(id, kk, (double)ob[key]);
  933. if (ob[key].holds(typeof(string)))
  934. db.set_property_string(id, kk, (string)ob[key]);
  935. if (ob[key].holds(typeof(Guid)))
  936. db.set_property_guid(id, kk, (Guid)ob[key]);
  937. if (ob[key].holds(typeof(Vector3)))
  938. db.set_property_vector3(id, kk, (Vector3)ob[key]);
  939. if (ob[key].holds(typeof(Quaternion)))
  940. db.set_property_quaternion(id, kk, (Quaternion)ob[key]);
  941. }
  942. }
  943. }
  944. public void undo()
  945. {
  946. if (_undo_points.size() == 0)
  947. return;
  948. RestorePoint rp = _undo_points.read_restore_point();
  949. _redo_points.write_restore_point(rp.id, _redo.size(), rp.data);
  950. undo_until(rp.size);
  951. undo_redo(true, rp.id, rp.data);
  952. }
  953. public void redo()
  954. {
  955. if (_redo_points.size() == 0)
  956. return;
  957. RestorePoint rp = _redo_points.read_restore_point();
  958. _undo_points.write_restore_point(rp.id, _undo.size(), rp.data);
  959. redo_until(rp.size);
  960. undo_redo(false, rp.id, rp.data);
  961. }
  962. private void undo_until(uint32 size)
  963. {
  964. undo_redo_until(size, _undo, _redo);
  965. }
  966. private void redo_until(uint32 size)
  967. {
  968. undo_redo_until(size, _redo, _undo);
  969. }
  970. private void undo_redo_until(uint32 size, Stack undo, Stack redo)
  971. {
  972. while (undo.size() != size)
  973. {
  974. uint32 type = undo.peek_type();
  975. if (type == Action.CREATE)
  976. {
  977. Action t = undo.read_action();
  978. assert(t == Action.CREATE);
  979. Guid id = undo.read_guid();
  980. redo.write_destroy_action(id);
  981. create_internal(id);
  982. }
  983. else if (type == Action.DESTROY)
  984. {
  985. Action t = undo.read_action();
  986. assert(t == Action.DESTROY);
  987. Guid id = undo.read_guid();
  988. redo.write_create_action(id);
  989. destroy_internal(id);
  990. }
  991. else if (type == Action.SET_PROPERTY_NULL)
  992. {
  993. Action t = undo.read_action();
  994. assert(t == Action.SET_PROPERTY_NULL);
  995. Guid id = undo.read_guid();
  996. string key = undo.read_string();
  997. if (get_data(id).has_key(key))
  998. {
  999. if (get_data(id)[key].holds(typeof(bool)))
  1000. redo.write_set_property_bool_action(id, key, (bool)get_data(id)[key]);
  1001. if (get_data(id)[key].holds(typeof(double)))
  1002. redo.write_set_property_double_action(id, key, (double)get_data(id)[key]);
  1003. if (get_data(id)[key].holds(typeof(string)))
  1004. redo.write_set_property_string_action(id, key, (string)get_data(id)[key]);
  1005. if (get_data(id)[key].holds(typeof(Guid)))
  1006. redo.write_set_property_guid_action(id, key, (Guid)get_data(id)[key]);
  1007. if (get_data(id)[key].holds(typeof(Vector3)))
  1008. redo.write_set_property_vector3_action(id, key, (Vector3)get_data(id)[key]);
  1009. if (get_data(id)[key].holds(typeof(Quaternion)))
  1010. redo.write_set_property_quaternion_action(id, key, (Quaternion)get_data(id)[key]);
  1011. }
  1012. else
  1013. {
  1014. redo.write_set_property_null_action(id, key);
  1015. }
  1016. set_property_internal(id, key, null);
  1017. }
  1018. else if (type == Action.SET_PROPERTY_BOOL)
  1019. {
  1020. Action t = undo.read_action();
  1021. assert(t == Action.SET_PROPERTY_BOOL);
  1022. Guid id = undo.read_guid();
  1023. string key = undo.read_string();
  1024. bool val = undo.read_bool();
  1025. if (get_data(id).has_key(key))
  1026. redo.write_set_property_bool_action(id, key, (bool)get_data(id)[key]);
  1027. else
  1028. redo.write_set_property_null_action(id, key);
  1029. set_property_internal(id, key, val);
  1030. }
  1031. else if (type == Action.SET_PROPERTY_DOUBLE)
  1032. {
  1033. Action t = undo.read_action();
  1034. assert(t == Action.SET_PROPERTY_DOUBLE);
  1035. Guid id = undo.read_guid();
  1036. string key = undo.read_string();
  1037. double val = undo.read_double();
  1038. if (get_data(id).has_key(key))
  1039. redo.write_set_property_double_action(id, key, (double)get_data(id)[key]);
  1040. else
  1041. redo.write_set_property_null_action(id, key);
  1042. set_property_internal(id, key, val);
  1043. }
  1044. else if (type == Action.SET_PROPERTY_STRING)
  1045. {
  1046. Action t = undo.read_action();
  1047. assert(t == Action.SET_PROPERTY_STRING);
  1048. Guid id = undo.read_guid();
  1049. string key = undo.read_string();
  1050. string val = undo.read_string();
  1051. if (get_data(id).has_key(key))
  1052. redo.write_set_property_string_action(id, key, (string)get_data(id)[key]);
  1053. else
  1054. redo.write_set_property_null_action(id, key);
  1055. set_property_internal(id, key, val);
  1056. }
  1057. else if (type == Action.SET_PROPERTY_GUID)
  1058. {
  1059. Action t = undo.read_action();
  1060. assert(t == Action.SET_PROPERTY_GUID);
  1061. Guid id = undo.read_guid();
  1062. string key = undo.read_string();
  1063. Guid val = undo.read_guid();
  1064. if (get_data(id).has_key(key))
  1065. redo.write_set_property_guid_action(id, key, (Guid)get_data(id)[key]);
  1066. else
  1067. redo.write_set_property_null_action(id, key);
  1068. set_property_internal(id, key, val);
  1069. }
  1070. else if (type == Action.SET_PROPERTY_VECTOR3)
  1071. {
  1072. Action t = undo.read_action();
  1073. assert(t == Action.SET_PROPERTY_VECTOR3);
  1074. Guid id = undo.read_guid();
  1075. string key = undo.read_string();
  1076. Vector3 val = undo.read_vector3();
  1077. if (get_data(id).has_key(key))
  1078. redo.write_set_property_vector3_action(id, key, (Vector3)get_data(id)[key]);
  1079. else
  1080. redo.write_set_property_null_action(id, key);
  1081. set_property_internal(id, key, val);
  1082. }
  1083. else if (type == Action.SET_PROPERTY_QUATERNION)
  1084. {
  1085. Action t = undo.read_action();
  1086. assert(t == Action.SET_PROPERTY_QUATERNION);
  1087. Guid id = undo.read_guid();
  1088. string key = undo.read_string();
  1089. Quaternion val = undo.read_quaternion();
  1090. if (get_data(id).has_key(key))
  1091. redo.write_set_property_quaternion_action(id, key, (Quaternion)get_data(id)[key]);
  1092. else
  1093. redo.write_set_property_null_action(id, key);
  1094. set_property_internal(id, key, val);
  1095. }
  1096. else if (type == Action.ADD_TO_SET)
  1097. {
  1098. Action t = undo.read_action();
  1099. assert(t == Action.ADD_TO_SET);
  1100. Guid id = undo.read_guid();
  1101. string key = undo.read_string();
  1102. Guid item_id = undo.read_guid();
  1103. redo.write_remove_from_set_action(id, key, item_id);
  1104. add_to_set_internal(id, key, item_id);
  1105. }
  1106. else if (type == Action.REMOVE_FROM_SET)
  1107. {
  1108. Action t = undo.read_action();
  1109. assert(t == Action.REMOVE_FROM_SET);
  1110. Guid id = undo.read_guid();
  1111. string key = undo.read_string();
  1112. Guid item_id = undo.read_guid();
  1113. redo.write_add_to_set_action(id, key, item_id);
  1114. remove_from_set_internal(id, key, item_id);
  1115. }
  1116. }
  1117. }
  1118. }
  1119. }