attribute.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733
  1. /*
  2. * Copyright 2011-2013 Blender Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "render/image.h"
  17. #include "render/mesh.h"
  18. #include "render/attribute.h"
  19. #include "util/util_foreach.h"
  20. #include "util/util_transform.h"
  21. CCL_NAMESPACE_BEGIN
  22. /* Attribute */
  23. Attribute::~Attribute()
  24. {
  25. /* for voxel data, we need to remove the image from the image manager */
  26. if (element == ATTR_ELEMENT_VOXEL) {
  27. VoxelAttribute *voxel_data = data_voxel();
  28. if (voxel_data && voxel_data->slot != -1) {
  29. voxel_data->manager->remove_image(voxel_data->slot);
  30. }
  31. }
  32. }
  33. void Attribute::set(ustring name_, TypeDesc type_, AttributeElement element_)
  34. {
  35. name = name_;
  36. type = type_;
  37. element = element_;
  38. std = ATTR_STD_NONE;
  39. flags = 0;
  40. /* string and matrix not supported! */
  41. assert(type == TypeDesc::TypeFloat || type == TypeDesc::TypeColor ||
  42. type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
  43. type == TypeDesc::TypeNormal || type == TypeDesc::TypeMatrix || type == TypeFloat2);
  44. }
  45. void Attribute::resize(Mesh *mesh, AttributePrimitive prim, bool reserve_only)
  46. {
  47. if (reserve_only) {
  48. buffer.reserve(buffer_size(mesh, prim));
  49. }
  50. else {
  51. buffer.resize(buffer_size(mesh, prim), 0);
  52. }
  53. }
  54. void Attribute::resize(size_t num_elements)
  55. {
  56. buffer.resize(num_elements * data_sizeof(), 0);
  57. }
  58. void Attribute::add(const float &f)
  59. {
  60. assert(data_sizeof() == sizeof(float));
  61. char *data = (char *)&f;
  62. size_t size = sizeof(f);
  63. for (size_t i = 0; i < size; i++)
  64. buffer.push_back(data[i]);
  65. }
  66. void Attribute::add(const uchar4 &f)
  67. {
  68. assert(data_sizeof() == sizeof(uchar4));
  69. char *data = (char *)&f;
  70. size_t size = sizeof(f);
  71. for (size_t i = 0; i < size; i++)
  72. buffer.push_back(data[i]);
  73. }
  74. void Attribute::add(const float2 &f)
  75. {
  76. assert(data_sizeof() == sizeof(float2));
  77. char *data = (char *)&f;
  78. size_t size = sizeof(f);
  79. for (size_t i = 0; i < size; i++)
  80. buffer.push_back(data[i]);
  81. }
  82. void Attribute::add(const float3 &f)
  83. {
  84. assert(data_sizeof() == sizeof(float3));
  85. char *data = (char *)&f;
  86. size_t size = sizeof(f);
  87. for (size_t i = 0; i < size; i++)
  88. buffer.push_back(data[i]);
  89. }
  90. void Attribute::add(const Transform &f)
  91. {
  92. assert(data_sizeof() == sizeof(Transform));
  93. char *data = (char *)&f;
  94. size_t size = sizeof(f);
  95. for (size_t i = 0; i < size; i++)
  96. buffer.push_back(data[i]);
  97. }
  98. void Attribute::add(const VoxelAttribute &f)
  99. {
  100. assert(data_sizeof() == sizeof(VoxelAttribute));
  101. char *data = (char *)&f;
  102. size_t size = sizeof(f);
  103. for (size_t i = 0; i < size; i++)
  104. buffer.push_back(data[i]);
  105. }
  106. void Attribute::add(const char *data)
  107. {
  108. size_t size = data_sizeof();
  109. for (size_t i = 0; i < size; i++)
  110. buffer.push_back(data[i]);
  111. }
  112. size_t Attribute::data_sizeof() const
  113. {
  114. if (element == ATTR_ELEMENT_VOXEL)
  115. return sizeof(VoxelAttribute);
  116. else if (element == ATTR_ELEMENT_CORNER_BYTE)
  117. return sizeof(uchar4);
  118. else if (type == TypeDesc::TypeFloat)
  119. return sizeof(float);
  120. else if (type == TypeFloat2)
  121. return sizeof(float2);
  122. else if (type == TypeDesc::TypeMatrix)
  123. return sizeof(Transform);
  124. else
  125. return sizeof(float3);
  126. }
  127. size_t Attribute::element_size(Mesh *mesh, AttributePrimitive prim) const
  128. {
  129. if (flags & ATTR_FINAL_SIZE) {
  130. return buffer.size() / data_sizeof();
  131. }
  132. size_t size;
  133. switch (element) {
  134. case ATTR_ELEMENT_OBJECT:
  135. case ATTR_ELEMENT_MESH:
  136. case ATTR_ELEMENT_VOXEL:
  137. size = 1;
  138. break;
  139. case ATTR_ELEMENT_VERTEX:
  140. size = mesh->verts.size() + mesh->num_ngons;
  141. if (prim == ATTR_PRIM_SUBD) {
  142. size -= mesh->num_subd_verts;
  143. }
  144. break;
  145. case ATTR_ELEMENT_VERTEX_MOTION:
  146. size = (mesh->verts.size() + mesh->num_ngons) * (mesh->motion_steps - 1);
  147. if (prim == ATTR_PRIM_SUBD) {
  148. size -= mesh->num_subd_verts * (mesh->motion_steps - 1);
  149. }
  150. break;
  151. case ATTR_ELEMENT_FACE:
  152. if (prim == ATTR_PRIM_TRIANGLE) {
  153. size = mesh->num_triangles();
  154. }
  155. else {
  156. size = mesh->subd_faces.size() + mesh->num_ngons;
  157. }
  158. break;
  159. case ATTR_ELEMENT_CORNER:
  160. case ATTR_ELEMENT_CORNER_BYTE:
  161. if (prim == ATTR_PRIM_TRIANGLE) {
  162. size = mesh->num_triangles() * 3;
  163. }
  164. else {
  165. size = mesh->subd_face_corners.size() + mesh->num_ngons;
  166. }
  167. break;
  168. case ATTR_ELEMENT_CURVE:
  169. size = mesh->num_curves();
  170. break;
  171. case ATTR_ELEMENT_CURVE_KEY:
  172. size = mesh->curve_keys.size();
  173. break;
  174. case ATTR_ELEMENT_CURVE_KEY_MOTION:
  175. size = mesh->curve_keys.size() * (mesh->motion_steps - 1);
  176. break;
  177. default:
  178. size = 0;
  179. break;
  180. }
  181. return size;
  182. }
  183. size_t Attribute::buffer_size(Mesh *mesh, AttributePrimitive prim) const
  184. {
  185. return element_size(mesh, prim) * data_sizeof();
  186. }
  187. bool Attribute::same_storage(TypeDesc a, TypeDesc b)
  188. {
  189. if (a == b)
  190. return true;
  191. if (a == TypeDesc::TypeColor || a == TypeDesc::TypePoint || a == TypeDesc::TypeVector ||
  192. a == TypeDesc::TypeNormal) {
  193. if (b == TypeDesc::TypeColor || b == TypeDesc::TypePoint || b == TypeDesc::TypeVector ||
  194. b == TypeDesc::TypeNormal) {
  195. return true;
  196. }
  197. }
  198. return false;
  199. }
  200. void Attribute::zero_data(void *dst)
  201. {
  202. memset(dst, 0, data_sizeof());
  203. }
  204. void Attribute::add_with_weight(void *dst, void *src, float weight)
  205. {
  206. if (element == ATTR_ELEMENT_CORNER_BYTE) {
  207. for (int i = 0; i < 4; i++) {
  208. ((uchar *)dst)[i] += uchar(((uchar *)src)[i] * weight);
  209. }
  210. }
  211. else if (same_storage(type, TypeDesc::TypeFloat)) {
  212. *((float *)dst) += *((float *)src) * weight;
  213. }
  214. else if (same_storage(type, TypeFloat2)) {
  215. *((float2 *)dst) += *((float2 *)src) * weight;
  216. }
  217. else if (same_storage(type, TypeDesc::TypeVector)) {
  218. *((float4 *)dst) += *((float4 *)src) * weight;
  219. }
  220. else {
  221. assert(!"not implemented for this type");
  222. }
  223. }
  224. const char *Attribute::standard_name(AttributeStandard std)
  225. {
  226. switch (std) {
  227. case ATTR_STD_VERTEX_NORMAL:
  228. return "N";
  229. case ATTR_STD_FACE_NORMAL:
  230. return "Ng";
  231. case ATTR_STD_UV:
  232. return "uv";
  233. case ATTR_STD_GENERATED:
  234. return "generated";
  235. case ATTR_STD_GENERATED_TRANSFORM:
  236. return "generated_transform";
  237. case ATTR_STD_UV_TANGENT:
  238. return "tangent";
  239. case ATTR_STD_UV_TANGENT_SIGN:
  240. return "tangent_sign";
  241. case ATTR_STD_POSITION_UNDEFORMED:
  242. return "undeformed";
  243. case ATTR_STD_POSITION_UNDISPLACED:
  244. return "undisplaced";
  245. case ATTR_STD_MOTION_VERTEX_POSITION:
  246. return "motion_P";
  247. case ATTR_STD_MOTION_VERTEX_NORMAL:
  248. return "motion_N";
  249. case ATTR_STD_PARTICLE:
  250. return "particle";
  251. case ATTR_STD_CURVE_INTERCEPT:
  252. return "curve_intercept";
  253. case ATTR_STD_CURVE_RANDOM:
  254. return "curve_random";
  255. case ATTR_STD_PTEX_FACE_ID:
  256. return "ptex_face_id";
  257. case ATTR_STD_PTEX_UV:
  258. return "ptex_uv";
  259. case ATTR_STD_VOLUME_DENSITY:
  260. return "density";
  261. case ATTR_STD_VOLUME_COLOR:
  262. return "color";
  263. case ATTR_STD_VOLUME_FLAME:
  264. return "flame";
  265. case ATTR_STD_VOLUME_HEAT:
  266. return "heat";
  267. case ATTR_STD_VOLUME_TEMPERATURE:
  268. return "temperature";
  269. case ATTR_STD_VOLUME_VELOCITY:
  270. return "velocity";
  271. case ATTR_STD_POINTINESS:
  272. return "pointiness";
  273. case ATTR_STD_NOT_FOUND:
  274. case ATTR_STD_NONE:
  275. case ATTR_STD_NUM:
  276. return "";
  277. }
  278. return "";
  279. }
  280. AttributeStandard Attribute::name_standard(const char *name)
  281. {
  282. if (name) {
  283. for (int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++) {
  284. if (strcmp(name, Attribute::standard_name((AttributeStandard)std)) == 0) {
  285. return (AttributeStandard)std;
  286. }
  287. }
  288. }
  289. return ATTR_STD_NONE;
  290. }
  291. /* Attribute Set */
  292. AttributeSet::AttributeSet()
  293. {
  294. triangle_mesh = NULL;
  295. curve_mesh = NULL;
  296. subd_mesh = NULL;
  297. }
  298. AttributeSet::~AttributeSet()
  299. {
  300. }
  301. Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement element)
  302. {
  303. Attribute *attr = find(name);
  304. if (attr) {
  305. /* return if same already exists */
  306. if (attr->type == type && attr->element == element)
  307. return attr;
  308. /* overwrite attribute with same name but different type/element */
  309. remove(name);
  310. }
  311. #if __cplusplus >= 201103L
  312. attributes.emplace_back();
  313. attr = &attributes.back();
  314. attr->set(name, type, element);
  315. #else
  316. {
  317. Attribute attr_temp;
  318. attr_temp.set(name, type, element);
  319. attributes.push_back(attr_temp);
  320. attr = &attributes.back();
  321. }
  322. #endif
  323. /* this is weak .. */
  324. if (triangle_mesh)
  325. attr->resize(triangle_mesh, ATTR_PRIM_TRIANGLE, false);
  326. if (curve_mesh)
  327. attr->resize(curve_mesh, ATTR_PRIM_CURVE, false);
  328. if (subd_mesh)
  329. attr->resize(subd_mesh, ATTR_PRIM_SUBD, false);
  330. return attr;
  331. }
  332. Attribute *AttributeSet::find(ustring name) const
  333. {
  334. foreach (const Attribute &attr, attributes)
  335. if (attr.name == name)
  336. return (Attribute *)&attr;
  337. return NULL;
  338. }
  339. void AttributeSet::remove(ustring name)
  340. {
  341. Attribute *attr = find(name);
  342. if (attr) {
  343. list<Attribute>::iterator it;
  344. for (it = attributes.begin(); it != attributes.end(); it++) {
  345. if (&*it == attr) {
  346. attributes.erase(it);
  347. return;
  348. }
  349. }
  350. }
  351. }
  352. Attribute *AttributeSet::add(AttributeStandard std, ustring name)
  353. {
  354. Attribute *attr = NULL;
  355. if (name == ustring())
  356. name = Attribute::standard_name(std);
  357. if (triangle_mesh || subd_mesh) {
  358. switch (std) {
  359. case ATTR_STD_VERTEX_NORMAL:
  360. attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX);
  361. break;
  362. case ATTR_STD_FACE_NORMAL:
  363. attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_FACE);
  364. break;
  365. case ATTR_STD_UV:
  366. attr = add(name, TypeFloat2, ATTR_ELEMENT_CORNER);
  367. break;
  368. case ATTR_STD_UV_TANGENT:
  369. attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
  370. break;
  371. case ATTR_STD_UV_TANGENT_SIGN:
  372. attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER);
  373. break;
  374. case ATTR_STD_GENERATED:
  375. case ATTR_STD_POSITION_UNDEFORMED:
  376. case ATTR_STD_POSITION_UNDISPLACED:
  377. attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
  378. break;
  379. case ATTR_STD_MOTION_VERTEX_POSITION:
  380. attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX_MOTION);
  381. break;
  382. case ATTR_STD_MOTION_VERTEX_NORMAL:
  383. attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX_MOTION);
  384. break;
  385. case ATTR_STD_PTEX_FACE_ID:
  386. attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_FACE);
  387. break;
  388. case ATTR_STD_PTEX_UV:
  389. attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
  390. break;
  391. case ATTR_STD_GENERATED_TRANSFORM:
  392. attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
  393. break;
  394. case ATTR_STD_VOLUME_DENSITY:
  395. case ATTR_STD_VOLUME_FLAME:
  396. case ATTR_STD_VOLUME_HEAT:
  397. case ATTR_STD_VOLUME_TEMPERATURE:
  398. attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VOXEL);
  399. break;
  400. case ATTR_STD_VOLUME_COLOR:
  401. attr = add(name, TypeDesc::TypeColor, ATTR_ELEMENT_VOXEL);
  402. break;
  403. case ATTR_STD_VOLUME_VELOCITY:
  404. attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_VOXEL);
  405. break;
  406. case ATTR_STD_POINTINESS:
  407. attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VERTEX);
  408. break;
  409. default:
  410. assert(0);
  411. break;
  412. }
  413. }
  414. else if (curve_mesh) {
  415. switch (std) {
  416. case ATTR_STD_UV:
  417. attr = add(name, TypeFloat2, ATTR_ELEMENT_CURVE);
  418. break;
  419. case ATTR_STD_GENERATED:
  420. attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
  421. break;
  422. case ATTR_STD_MOTION_VERTEX_POSITION:
  423. attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY_MOTION);
  424. break;
  425. case ATTR_STD_CURVE_INTERCEPT:
  426. attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE_KEY);
  427. break;
  428. case ATTR_STD_CURVE_RANDOM:
  429. attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE);
  430. break;
  431. case ATTR_STD_GENERATED_TRANSFORM:
  432. attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
  433. break;
  434. case ATTR_STD_POINTINESS:
  435. attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VERTEX);
  436. break;
  437. default:
  438. assert(0);
  439. break;
  440. }
  441. }
  442. attr->std = std;
  443. return attr;
  444. }
  445. Attribute *AttributeSet::find(AttributeStandard std) const
  446. {
  447. foreach (const Attribute &attr, attributes)
  448. if (attr.std == std)
  449. return (Attribute *)&attr;
  450. return NULL;
  451. }
  452. void AttributeSet::remove(AttributeStandard std)
  453. {
  454. Attribute *attr = find(std);
  455. if (attr) {
  456. list<Attribute>::iterator it;
  457. for (it = attributes.begin(); it != attributes.end(); it++) {
  458. if (&*it == attr) {
  459. attributes.erase(it);
  460. return;
  461. }
  462. }
  463. }
  464. }
  465. Attribute *AttributeSet::find(AttributeRequest &req)
  466. {
  467. if (req.std == ATTR_STD_NONE)
  468. return find(req.name);
  469. else
  470. return find(req.std);
  471. }
  472. void AttributeSet::remove(Attribute *attribute)
  473. {
  474. if (attribute->std == ATTR_STD_NONE) {
  475. remove(attribute->name);
  476. }
  477. else {
  478. remove(attribute->std);
  479. }
  480. }
  481. void AttributeSet::resize(bool reserve_only)
  482. {
  483. foreach (Attribute &attr, attributes) {
  484. if (triangle_mesh)
  485. attr.resize(triangle_mesh, ATTR_PRIM_TRIANGLE, reserve_only);
  486. if (curve_mesh)
  487. attr.resize(curve_mesh, ATTR_PRIM_CURVE, reserve_only);
  488. if (subd_mesh)
  489. attr.resize(subd_mesh, ATTR_PRIM_SUBD, reserve_only);
  490. }
  491. }
  492. void AttributeSet::clear(bool preserve_voxel_data)
  493. {
  494. if (preserve_voxel_data) {
  495. list<Attribute>::iterator it;
  496. for (it = attributes.begin(); it != attributes.end();) {
  497. if (it->element == ATTR_ELEMENT_VOXEL || it->std == ATTR_STD_GENERATED_TRANSFORM) {
  498. it++;
  499. }
  500. else {
  501. attributes.erase(it++);
  502. }
  503. }
  504. }
  505. else {
  506. attributes.clear();
  507. }
  508. }
  509. /* AttributeRequest */
  510. AttributeRequest::AttributeRequest(ustring name_)
  511. {
  512. name = name_;
  513. std = ATTR_STD_NONE;
  514. triangle_type = TypeDesc::TypeFloat;
  515. triangle_desc.element = ATTR_ELEMENT_NONE;
  516. triangle_desc.offset = 0;
  517. triangle_desc.type = NODE_ATTR_FLOAT;
  518. curve_type = TypeDesc::TypeFloat;
  519. curve_desc.element = ATTR_ELEMENT_NONE;
  520. curve_desc.offset = 0;
  521. curve_desc.type = NODE_ATTR_FLOAT;
  522. subd_type = TypeDesc::TypeFloat;
  523. subd_desc.element = ATTR_ELEMENT_NONE;
  524. subd_desc.offset = 0;
  525. subd_desc.type = NODE_ATTR_FLOAT;
  526. }
  527. AttributeRequest::AttributeRequest(AttributeStandard std_)
  528. {
  529. name = ustring();
  530. std = std_;
  531. triangle_type = TypeDesc::TypeFloat;
  532. triangle_desc.element = ATTR_ELEMENT_NONE;
  533. triangle_desc.offset = 0;
  534. triangle_desc.type = NODE_ATTR_FLOAT;
  535. curve_type = TypeDesc::TypeFloat;
  536. curve_desc.element = ATTR_ELEMENT_NONE;
  537. curve_desc.offset = 0;
  538. curve_desc.type = NODE_ATTR_FLOAT;
  539. subd_type = TypeDesc::TypeFloat;
  540. subd_desc.element = ATTR_ELEMENT_NONE;
  541. subd_desc.offset = 0;
  542. subd_desc.type = NODE_ATTR_FLOAT;
  543. }
  544. /* AttributeRequestSet */
  545. AttributeRequestSet::AttributeRequestSet()
  546. {
  547. }
  548. AttributeRequestSet::~AttributeRequestSet()
  549. {
  550. }
  551. bool AttributeRequestSet::modified(const AttributeRequestSet &other)
  552. {
  553. if (requests.size() != other.requests.size())
  554. return true;
  555. for (size_t i = 0; i < requests.size(); i++) {
  556. bool found = false;
  557. for (size_t j = 0; j < requests.size() && !found; j++)
  558. if (requests[i].name == other.requests[j].name && requests[i].std == other.requests[j].std) {
  559. found = true;
  560. }
  561. if (!found) {
  562. return true;
  563. }
  564. }
  565. return false;
  566. }
  567. void AttributeRequestSet::add(ustring name)
  568. {
  569. foreach (AttributeRequest &req, requests) {
  570. if (req.name == name) {
  571. return;
  572. }
  573. }
  574. requests.push_back(AttributeRequest(name));
  575. }
  576. void AttributeRequestSet::add(AttributeStandard std)
  577. {
  578. foreach (AttributeRequest &req, requests)
  579. if (req.std == std)
  580. return;
  581. requests.push_back(AttributeRequest(std));
  582. }
  583. void AttributeRequestSet::add(AttributeRequestSet &reqs)
  584. {
  585. foreach (AttributeRequest &req, reqs.requests) {
  586. if (req.std == ATTR_STD_NONE)
  587. add(req.name);
  588. else
  589. add(req.std);
  590. }
  591. }
  592. void AttributeRequestSet::add_standard(ustring name)
  593. {
  594. if (name.empty()) {
  595. return;
  596. }
  597. AttributeStandard std = Attribute::name_standard(name.c_str());
  598. if (std) {
  599. add(std);
  600. }
  601. else {
  602. add(name);
  603. }
  604. }
  605. bool AttributeRequestSet::find(ustring name)
  606. {
  607. foreach (AttributeRequest &req, requests)
  608. if (req.name == name)
  609. return true;
  610. return false;
  611. }
  612. bool AttributeRequestSet::find(AttributeStandard std)
  613. {
  614. foreach (AttributeRequest &req, requests)
  615. if (req.std == std)
  616. return true;
  617. return false;
  618. }
  619. size_t AttributeRequestSet::size()
  620. {
  621. return requests.size();
  622. }
  623. void AttributeRequestSet::clear()
  624. {
  625. requests.clear();
  626. }
  627. CCL_NAMESPACE_END