00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "vgfx.h"
00036
00037 #include <fstream>
00038
00039 #include "common/wave_ex.h"
00040 #include "perf/perf.h"
00041 #include "util/file.h"
00042 #include "util/parsing.h"
00043 #include "util/token_stream.h"
00044
00045
00046 namespace vgfx {
00047
00048 static const eParseBehavior s_line_behavior = (eParseBehavior) (
00049 eParse_StripComments |
00050 eParse_StripBogus |
00051 eParse_RespectQuotes
00052 );
00053
00054
00055
00056
00057
00058
00059
00060
00061 static bool
00062 requiresQuotes
00063 (
00064 IN const char * p
00065 )
00066 throw()
00067 {
00068 ASSERT(p, "null string passed to requiresQuotes()");
00069
00070 if (!*p)
00071 return true;
00072
00073 while (*p) {
00074 if (isspace(*p))
00075 return true;
00076 ++p;
00077 }
00078
00079 return false;
00080 }
00081
00082
00083
00084 static void
00085 getFunctionValue
00086 (
00087 IN ObjectMap * map,
00088 const char * fn_name,
00089 OUT std::string& value
00090 )
00091 {
00092 ASSERT(map, "null object map");
00093 ASSERT(fn_name, "null function name");
00094
00095
00096 if (!strcmp("_newID()", fn_name)) {
00097
00098 map->newObjectID(NULL, value);
00099 } else {
00100 WAVE_EX(wex);
00101 wex << "Unknown function: '" << fn_name << "'";
00102 }
00103
00104 }
00105
00106
00107
00108 static bool
00109 isOperation
00110 (
00111 IN const char * s
00112 )
00113 throw()
00114 {
00115 ASSERT(s, "null string passed in to isOperation()");
00116
00117 if (!strcmp("-", s) ||
00118 !strcmp("+", s) ||
00119 !strcmp("*", s) ||
00120 !strcmp("/", s))
00121 return true;
00122 return false;
00123 }
00124
00125
00126
00127 static float
00128 operate
00129 (
00130 IN float left,
00131 IN char op,
00132 IN float right
00133 )
00134 throw()
00135 {
00136 switch (op) {
00137 case '-': return left - right;
00138 case '+': return left + right;
00139 case '*': return left * right;
00140 case '/': return left / right;
00141 }
00142
00143 WAVE_EX(wex);
00144 wex << "Unrecognized operation! '" << op << "'";
00145 return -1;
00146 }
00147
00148
00149
00150 static void
00151 computeValue
00152 (
00153 IN ObjectMap * map,
00154 IN const char * raw,
00155 IN const dictionary_t& variables,
00156 OUT std::string& computed
00157 );
00158
00159
00160
00161 static void
00162 evaluate
00163 (
00164 IN ObjectMap * map,
00165 IN const dictionary_t& variables,
00166 IN const char * expr,
00167 OUT std::string& result
00168 )
00169 {
00170 ASSERT(map, "null object map in evaluate()");
00171 ASSERT(expr, "null expression");
00172
00173 result.clear();
00174
00175
00176 DPRINTF("WARNING: expression parsing is still primitive");
00177
00178 std::string token;
00179 float value = 0.0;
00180 char operation = 0;
00181 bool have_left = false;
00182 const char * cursor = expr;
00183 while (true) {
00184 cursor = getNextTokenFromString(cursor, token, eParse_None);
00185 if (!token[0])
00186 break;
00187
00188 float right = 0.0;
00189 bool have_right = false;
00190 if (!isOperation(token.c_str())) {
00191 std::string val;
00192 computeValue(map, token.c_str(), variables, val);
00193 right = atof(val.c_str());
00194
00195 have_right = true;
00196 } else {
00197 if (operation) {
00198 WAVE_EX(wex);
00199 wex << "encountered two operators in a row? '";
00200 wex << operation << "' and '" << token << "'";
00201 }
00202 operation = token[0];
00203 }
00204
00205
00206 if (have_right) {
00207 if (!have_left) {
00208
00209 have_left = true;
00210 have_right = false;
00211 value = right;
00212 } else {
00213
00214 if (!operation) {
00215 WAVE_EX(wex);
00216 wex << "Have left and right values, ";
00217 wex << "but no operator between them!";
00218 }
00219
00220 value = operate(value, operation, right);
00221 have_left = true;
00222 have_right = false;
00223 operation = 0;
00224 }
00225 }
00226 }
00227
00228 const int bufsize = 32;
00229 char buffer[bufsize];
00230 sprintf(buffer, "%8.6f", value);
00231 result = buffer;
00232 }
00233
00234
00235
00236 static void
00237 computeValue
00238 (
00239 IN ObjectMap * map,
00240 IN const char * raw,
00241 IN const dictionary_t& variables,
00242 OUT std::string& computed
00243 )
00244 {
00245 ASSERT(raw, "null raw value");
00246 computed.clear();
00247
00248 if ('$' == raw[0]) {
00249
00250
00251 computed = getRequiredValue(variables, raw + 1);
00252 } else if ('&' == raw[0]) {
00253
00254
00255 getFunctionValue(map, raw + 1, computed);
00256 } else if ('=' == raw[0]) {
00257
00258 evaluate(map, variables, raw + 1, computed);
00259 } else {
00260 computed = raw;
00261 }
00262 }
00263
00264
00265
00266 static float
00267 getFloat
00268 (
00269 IN ObjectMap * map,
00270 IN const dictionary_t& variables,
00271 IN const dictionary_t& data,
00272 IN const char * key,
00273 IN const char * default_value
00274 )
00275 {
00276 ASSERT(key, "null key name in getFloat()");
00277 ASSERT(default_value, "null default value in getFloat()");
00278
00279 const char * value = NULL;
00280 if (default_value)
00281 value = getOptionalValue(data, key, default_value);
00282 else
00283 value = getRequiredValue(data, key);
00284 ASSERT(value, "should have value now");
00285
00286 std::string computed;
00287 computeValue(map, value, variables, computed);
00288
00289 return atof(computed.c_str());
00290 }
00291
00292
00293
00294 static void
00295 processTile
00296 (
00297 IN ObjectMap * map,
00298 IN const char * cursor,
00299 IN const dictionary_t& variables,
00300 IO std::ostream& stream
00301 )
00302 {
00303 ASSERT(map, "null object map in processTile()");
00304 ASSERT(cursor, "null tile declaration line");
00305 ASSERT(stream.good(), "bad stream in processTile()");
00306
00307 dictionary_t data;
00308 getDictionaryFromString(cursor, "parsing tile declaration line", data);
00309
00310
00311 float x_start = getFloat(map, variables, data, "xStart", "0.0");
00312 float x_inc = getFloat(map, variables, data, "xInc", "0.0");
00313 float x_end = getFloat(map, variables, data, "xEnd", "0.0");
00314 if (x_end != x_start && !x_inc) {
00315 WAVE_EX(wex);
00316 wex << "Cannot tile in x-direction: missing increment 'xInc'";
00317 }
00318 if (x_inc < 0) {
00319 WAVE_EX(wex);
00320 wex << "Bad x-increment: " << x_inc;
00321 }
00322
00323 float y_start = getFloat(map, variables, data, "yStart", "0.0");
00324 float y_inc = getFloat(map, variables, data, "yInc", "0.0");
00325 float y_end = getFloat(map, variables, data, "yEnd", "0.0");
00326 if (y_end != y_start && !y_inc) {
00327 WAVE_EX(wex);
00328 wex << "Cannot tile in y-direction: missing increment 'yInc'";
00329 }
00330 if (y_inc < 0) {
00331 WAVE_EX(wex);
00332 wex << "Bad y-increment: " << y_inc;
00333 }
00334
00335
00336 const char * raw_id = getRequiredValue(data, "id");
00337 std::string id;
00338 computeValue(map, raw_id, variables, id);
00339
00340
00341
00342
00343 float x = x_start;
00344 while (x <= x_end) {
00345
00346 float y = y_start;
00347 while (y <= y_end) {
00348 std::string tag_id;
00349 map->newObjectID("tag", tag_id);
00350 stream << "object tag " << tag_id << " id " << id;
00351 stream << " x " << x << " y " << y << "\n";
00352
00353 if (!y_inc)
00354 break;
00355 y += y_inc;
00356 }
00357
00358 if (!x_inc)
00359 break;
00360 x += x_inc;
00361 }
00362 }
00363
00364
00365
00366 static void
00367 processVariable
00368 (
00369 IN ObjectMap * map,
00370 IN const char * cursor,
00371 IN const dictionary_t& in_params,
00372 IN const objtree::property_set_t& pub,
00373 IO dictionary_t& variables
00374 )
00375 {
00376 ASSERT(map, "null object map in processVariable()");
00377 ASSERT(cursor, "null variable declaration line");
00378
00379 dictionary_t data;
00380 getDictionaryFromString(cursor, "parsing variable declaration line",
00381 data);
00382
00383
00384 const char * name = getRequiredValue(data, "name");
00385 if (!objtree::isValidPropertyName(name)) {
00386 WAVE_EX(wex);
00387 wex << "Invalid variable name: '" << name << "'";
00388 }
00389
00390 const char * value = getValue(in_params, name);
00391 if (!value) {
00392
00393 value = pub.getValue(name);
00394 if (!value) {
00395
00396 value = getValue(data, "value");
00397 if (!value) {
00398 WAVE_EX(wex);
00399 wex << "variable '" << name << "' has ";
00400 wex << "no default value, and no value was ";
00401 wex << "passed in by caller.";
00402 }
00403 }
00404 }
00405 ASSERT(value, "Should have value for variable '%s'", name);
00406
00407
00408 std::string computed;
00409 computeValue(map, value, variables, computed);
00410
00411
00412 variables[name] = computed;
00413
00414 }
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424 class Function : public Primitive {
00425 public:
00426 ~Function(void) throw() { }
00427
00428
00429 void initialize(IN std::istream& stream);
00430 const VecString& getLines(void) const throw() { return m_lines; }
00431 const objtree::property_set_t& getPublic(void) const throw()
00432 { return m_public; }
00433
00434
00435 const char * getType(void) const throw() { return "function"; }
00436 void persist(OUT std::ostream& stream) const;
00437 void listContainers(IN const VecString& path,
00438 OUT VecString& ids) const;
00439 bool doesContainerExist(IN const VecString& path) const;
00440 bool canCreateContainer(IN const VecString& path) const;
00441 void removeContainer(IN const VecString& path);
00442 void getContainerDictionary(IN const VecString& path,
00443 OUT dictionary_t& data) const;
00444 void setContainerDictionary(IN const VecString& path,
00445 IN const dictionary_t& data);
00446 void recalcBoundingRect(IN const char * tag_path,
00447 IN Drawer *, IN const xform_2d_t&) { }
00448 bool getBoundingRect(OUT rect_t& r) const throw() { return false; }
00449 void draw(IN Drawer * drawer,
00450 IN const rect_t& r_cm,
00451 IN const xform_2d_t& T) { }
00452
00453 private:
00454
00455 VecString m_lines;
00456 objtree::property_set_t m_public;
00457 };
00458
00459
00460
00461 void
00462 Function::persist
00463 (
00464 OUT std::ostream& stream
00465 )
00466 const
00467 {
00468 stream << "function {\n";
00469 stream << "\tid\t" << this->getID() << "\n";
00470 for (VecString::const_iterator i = m_lines.begin(); i != m_lines.end();
00471 ++i) {
00472 stream << *i << "\n";
00473 }
00474 stream << "}\n";
00475 }
00476
00477
00478
00479 void
00480 Function::listContainers
00481 (
00482 IN const VecString& path,
00483 OUT VecString& ids
00484 )
00485 const
00486 {
00487 ids.clear();
00488 if (1 != path.size() || path[0] != "public") {
00489 WAVE_EX(wex);
00490 wex << "Functions only support path='public' in listContainers()";
00491 }
00492
00493 for (objtree::property_set_t::const_iterator i = m_public.begin();
00494 i != m_public.end(); ++i) {
00495 ids.push_back(i->first);
00496 }
00497 }
00498
00499
00500
00501 bool
00502 Function::doesContainerExist
00503 (
00504 IN const VecString& path
00505 )
00506 const
00507 {
00508 if (2 != path.size())
00509 return false;
00510
00511 if ("public" != path[0])
00512 return false;
00513
00514 return !m_public.getProperty(path[1].c_str());
00515 }
00516
00517
00518
00519 bool
00520 Function::canCreateContainer
00521 (
00522 IN const VecString& path
00523 )
00524 const
00525 {
00526 if (2 != path.size())
00527 return false;
00528 if ("public" != path[0])
00529 return false;
00530 return objtree::isValidPropertyName(path[1].c_str());
00531 }
00532
00533
00534
00535 void
00536 Function::removeContainer
00537 (
00538 IN const VecString& path
00539 )
00540 {
00541 if (2 != path.size() || "public" != path[0]) {
00542 WAVE_EX(wex);
00543 wex << "invalid path in Function::removeContainer()";
00544 }
00545
00546 ASSERT(false, "who is removing function public properties?");
00547 }
00548
00549
00550
00551 void
00552 Function::getContainerDictionary
00553 (
00554 IN const VecString& path,
00555 OUT dictionary_t& data
00556 )
00557 const
00558 {
00559 data.clear();
00560 if (2 != path.size() || "public" != path[0]) {
00561 WAVE_EX(wex);
00562 wex << "invalid path in Function::getContainerDictionary()";
00563 }
00564
00565 const char * name = path[1].c_str();
00566 const objtree::property_t * p = m_public.getProperty(name);
00567 if (!p) {
00568 WAVE_EX(wex);
00569 wex << "Public property '" << name << "' not found in ";
00570 wex << "function '" << this->getID() << "'";
00571 }
00572
00573 for (objtree::property_t::const_iterator i = p->begin(); i != p->end();
00574 ++i) {
00575 const char * field = i->first.c_str();
00576 const char * value = i->second.c_str();
00577
00578 data[field] = value;
00579 }
00580 }
00581
00582
00583
00584 void
00585 Function::setContainerDictionary
00586 (
00587 IN const VecString& path,
00588 IN const dictionary_t& data
00589 )
00590 {
00591 if (2 != path.size() || "public" != path[0]) {
00592 WAVE_EX(wex);
00593 wex << "invalid path in Function::setContainerDictionary()";
00594 }
00595
00596 ASSERT(false, "Who is changing public parameters of functions?");
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610 }
00611
00612
00613
00614 void
00615 Function::initialize
00616 (
00617 IN std::istream& stream
00618 )
00619 {
00620 ASSERT(stream.good(), "bad stream passed to Function::create()");
00621
00622
00623 std::string line, token;
00624 int depth = 0;
00625 while (true) {
00626 line = getNextLineFromStream(stream, s_line_behavior);
00627 const char * cursor =
00628 getNextTokenFromString(line.c_str(), token, eParse_None);
00629 if ("" == token) {
00630 continue;
00631 }
00632
00633 if ("variable" == token) {
00634
00635 dictionary_t data;
00636 getDictionaryFromString(cursor, "parsing variable", data);
00637
00638 if (!strcmp("true", getOptionalValue(data, "public", "false"))) {
00639 objtree::property_t p;
00640 const char * name = getRequiredValue(data, "name");
00641
00642 for (dictionary_t::iterator i = data.begin();
00643 i != data.end(); ++i) {
00644 const char * field = i->first.c_str();
00645 if (!strcmp("name", field))
00646 continue;
00647 const char * value = i->second.c_str();
00648 p.setFieldValue(field, value);
00649 }
00650
00651 m_public[name] = p;
00652 }
00653 }
00654
00655
00656 if (strstr(line.c_str(), "{"))
00657 ++depth;
00658 if (strstr(line.c_str(), "}"))
00659 --depth;
00660
00661
00662 if (depth < 0) {
00663 ASSERT(-1 == depth, "Bad depth: %d", depth);
00664 break;
00665 }
00666
00667
00668
00669
00670 if (depth) {
00671 m_lines.push_back(line);
00672 continue;
00673 }
00674
00675
00676 if ("id" == token) {
00677 getNextTokenFromString(cursor, token, eParse_None);
00678 this->setID(token.c_str());
00679 continue;
00680 }
00681
00682
00683 m_lines.push_back(line);
00684 }
00685
00686
00687
00688 }
00689
00690
00691
00692 static void
00693 getScriptOutputId
00694 (
00695 IN const char * param_id,
00696 OUT std::string& output_id
00697 )
00698 {
00699 ASSERT(param_id, "null");
00700
00701 output_id = param_id;
00702 output_id += "ScriptOutput";
00703 }
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713 smart_ptr<Primitive>
00714 parseFunction
00715 (
00716 IN std::istream& stream,
00717 IN ObjectMap * map
00718 )
00719 {
00720 smart_ptr<Function> local = new Function;
00721 ASSERT(local, "out of memory");
00722
00723 local->initialize(stream);
00724
00725 return local;
00726 }
00727
00728
00729
00730 void
00731 invokeFunction
00732 (
00733 IN Primitive * in_function,
00734 IN ObjectMap * map,
00735 IN const dictionary_t& in_params,
00736 OUT std::ostream& out
00737 )
00738 {
00739 perf::Timer timer("vgfx::invokeFunction");
00740 ASSERT(in_function, "null function object");
00741 ASSERT(map, "null object map");
00742
00743 if (strcmp("function", in_function->getType())) {
00744 WAVE_EX(wex);
00745 wex << "Object '" << in_function->getID() << "' is not a ";
00746 wex << "function, it is a '" << in_function->getType() << "'";
00747 }
00748
00749 Function * function = dynamic_cast<Function *>(in_function);
00750 ASSERT(function, "this should work!");
00751
00752 dictionary_t variables;
00753 std::string token;
00754
00755 const VecString& lines = function->getLines();
00756 for (VecString::const_iterator i = lines.begin(); i != lines.end(); ++i)
00757 {
00758 const char * line = i->c_str();
00759
00760
00761 const char * cursor =
00762 getNextTokenFromString(line, token, eParse_None);
00763 if ("" == token) {
00764 DPRINTF("Weird: blank line in function???");
00765 continue;
00766 }
00767
00768
00769 if ("variable" == token) {
00770
00771 processVariable(map, cursor, in_params,
00772 function->getPublic(), variables);
00773 continue;
00774 } else if ("tile" == token) {
00775
00776 processTile(map, cursor, variables, out);
00777 } else {
00778
00779 out << token << " ";
00780 while (true) {
00781 cursor = getNextTokenFromString(cursor, token,
00782 eParse_None);
00783 if ("" == token)
00784 break;
00785
00786 std::string computed;
00787 computeValue(map, token.c_str(), variables,
00788 computed);
00789 const char * value = computed.c_str();
00790 if (requiresQuotes(value)) {
00791 out << "\"" << value << "\" ";
00792 } else {
00793 out << value << " ";
00794 }
00795 }
00796 out << "\n";
00797 }
00798 }
00799 }
00800
00801
00802
00803 Primitive *
00804 addFunctionFromPath
00805 (
00806 IN ObjectMap * map,
00807 IN const char * path
00808 )
00809 {
00810 ASSERT(map, "null");
00811 ASSERT(path, "null");
00812
00813
00814 std::string id;
00815 GetFileRoot(path, id);
00816
00817
00818
00819
00820
00821
00822
00823 Primitive * p = map->findObject(id.c_str());
00824 if (p) {
00825 DPRINTF("Already loaded script with id='%s'", id.c_str());
00826 return p;
00827 }
00828
00829
00830 std::ifstream infile(path);
00831 if (!infile.good()) {
00832 WAVE_EX(wex);
00833 wex << "Failed to open file for reading: " << path;
00834 }
00835
00836
00837 std::string unused, diagnostic;
00838 if (!processRequest(map, infile, false, unused, diagnostic)) {
00839 WAVE_EX(wex);
00840 wex << "Failed to load script: " << diagnostic;
00841 }
00842
00843
00844 p = map->findObject(id.c_str());
00845 if (!p) {
00846 WAVE_EX(wex);
00847 wex << "Malformed script: function id should match filename: ";
00848 wex << "'" << id << "'";
00849 }
00850
00851
00852 return p;
00853 }
00854
00855
00856
00857 void
00858 setScript
00859 (
00860 IN ObjectMap * map,
00861 IN const char * parent_id,
00862 IN const char * script_id,
00863 IN const objtree::property_set_t& pset_def,
00864 IO std::ostream& stream,
00865 OUT std::string& root
00866 )
00867 {
00868 perf::Timer timer("vgfx::setScript");
00869 ASSERT(map, "null");
00870 ASSERT(parent_id, "null");
00871 ASSERT(script_id, "null");
00872 ASSERT(stream.good(), "bad stream?");
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882 root = parent_id;
00883 root += "ScriptRoot";
00884 const char * root_id = root.c_str();
00885
00886 std::string out;
00887 getScriptOutputId(parent_id, out);
00888 const char * out_id = out.c_str();
00889
00890
00891 if (map->findObject(out_id)) {
00892 stream << "remove " << root_id << ".object.output\n";
00893 stream << "remove " << out_id << "\n";
00894 }
00895
00896
00897 if (map->findObject(root_id)) {
00898 stream << "remove " << parent_id << ".object.scriptParams\n";
00899 stream << "remove " << root << "\n";
00900 }
00901
00902
00903 stream << "add group {\n";
00904 stream << "id " << root_id << "\n";
00905 stream << "}\n";
00906
00907
00908 Primitive * fn = map->findObject(script_id);
00909 ASSERT(fn, "Need to add function object to map first! script='%s'",
00910 script_id);
00911
00912
00913 Primitive * p = map->findObject(parent_id);
00914 ASSERT(p, "Parent does not exist? '%s'", parent_id);
00915 rect_t r;
00916 p->getBoundingRect(r);
00917
00918
00919 dictionary_t data;
00920 data["rootId"] = out_id;
00921 data["width"] = getStringValue(r.right - r.left);
00922 data["height"] = getStringValue(r.bottom - r.top);
00923
00924
00925 VecString params;
00926 VecString path;
00927 path.push_back("public");
00928 fn->listContainers(path, params);
00929 for (VecString::const_iterator i = params.begin(); i != params.end();
00930 ++i) {
00931 const char * name = i->c_str();
00932
00933
00934 dictionary_t q;
00935 path.clear();
00936 path.push_back("public");
00937 path.push_back(name);
00938 fn->getContainerDictionary(path, q);
00939
00940
00941
00942 const char * value = pset_def.getValue(name);
00943 if (!value) {
00944
00945 value = getRequiredValue(q, "value");
00946 }
00947 data[name] = value;
00948
00949
00950 stream << "set " << root << ".meta." << name << " " << name;
00951 stream << " \"" << value << "\"\n";;
00952 }
00953
00954
00955 invokeFunction(fn, map, data, stream);
00956
00957
00958 stream << "set " << root << ".meta.parentId parentId ";
00959 stream << parent_id << "\n";
00960 stream << "set " << root << ".object.output id " << out << " z -1.0\n";
00961 stream << "set " << root << ".object.script id " << script_id << "\n";
00962
00963
00964 stream << "set " << parent_id << ".object.scriptParams id " << root << " z -1.0\n";
00965
00966
00967 }
00968
00969
00970
00971 void
00972 updateScriptParameters
00973 (
00974 IN ObjectMap * map,
00975 IN const char * parent_id,
00976 IN const objtree::property_set_t& pset,
00977 IO std::ostream& stream
00978 )
00979 {
00980 perf::Timer timer("vgfx::updateScriptParameters");
00981 ASSERT(map, "null");
00982 ASSERT(parent_id, "null");
00983 ASSERT(stream.good(), "bad stream");
00984
00985
00986
00987
00988
00989 vgfx::Primitive * params = map->findObject(parent_id);
00990 ASSERT(params, "should have a valid script parameter object '%s'",
00991 parent_id);
00992
00993
00994 VecString path;
00995 path.push_back("meta");
00996 path.push_back("parentId");
00997 dictionary_t data;
00998 params->getContainerDictionary(path, data);
00999 const char * grandparent_id = getRequiredValue(data, "parentId");
01000
01001 vgfx::Primitive * gp = map->findObject(grandparent_id);
01002 ASSERT(gp, "Grandparent does not exist? '%s'", grandparent_id);
01003
01004
01005 rect_t r;
01006 gp->getBoundingRect(r);
01007
01008
01009 std::string output_id;
01010 getScriptOutputId(grandparent_id, output_id);
01011
01012
01013 dictionary_t script_params;
01014 script_params["rootId"] = output_id;
01015 script_params["width"] = getStringValue(r.right - r.left);
01016 script_params["height"] = getStringValue(r.bottom - r.top);
01017
01018
01019 if (pset.getValue("width"))
01020 script_params["width"] = pset.getValue("width");
01021 if (pset.getValue("height"))
01022 script_params["height"] = pset.getValue("height");
01023
01024
01025 path.clear();
01026 path.push_back("object");
01027 path.push_back("script");
01028 params->getContainerDictionary(path, data);
01029 const char * script_id = getRequiredValue(data, "id");
01030
01031 vgfx::Primitive * fn = map->findObject(script_id);
01032 ASSERT(fn, "No such script object found? '%s'", script_id);
01033
01034
01035 path.clear();
01036 path.push_back("public");
01037 VecString props;
01038 fn->listContainers(path, props);
01039
01040
01041 for (VecString::const_iterator i = props.begin(); i != props.end();
01042 ++i) {
01043 const char * name = i->c_str();
01044 const char * value = pset.getValue(name);
01045 ASSERT(value, "Script public parameter '%s' not found in pset?",
01046 name);
01047
01048
01049 script_params[name] = value;
01050 }
01051
01052
01053 stream << "remove " << parent_id << ".object.output\n";
01054 stream << "remove " << output_id << "\n";
01055
01056
01057 invokeFunction(fn, map, script_params, stream);
01058
01059
01060 stream << "set " << parent_id << ".object.output id " << output_id << "\n";
01061 }
01062
01063
01064
01065 void
01066 resizeScript
01067 (
01068 IN ObjectMap * map,
01069 IN const char * parent_id,
01070 IN float width,
01071 IN float height,
01072 IO std::ostream& stream
01073 )
01074 {
01075 ASSERT(map, "null");
01076 ASSERT(parent_id, "null");
01077 ASSERT(width > 0, "bad width: %f", width);
01078 ASSERT(height > 0, "bad height: %f", height);
01079 ASSERT(stream.good(), "bad stream");
01080
01081
01082 Primitive * parent = map->findObject(parent_id);
01083 ASSERT(parent, "could not find script parent: '%s'", parent_id);
01084
01085
01086 const char * tag_path = "script";
01087 xform_2d_t T;
01088 visit_result_t vr;
01089 parent->getPrimitive(tag_path, T, vr);
01090 ASSERT(vr.p, "No script child for parent '%s'", parent_id);
01091 Primitive * script = vr.p;
01092
01093
01094 VecString path;
01095 path.push_back("public");
01096 VecString params;
01097 script->listContainers(path, params);
01098
01099 objtree::property_set_t pset;
01100
01101
01102 for (VecString::iterator i = params.begin(); i != params.end(); ++i) {
01103 const char * param = i->c_str();
01104 DPRINTF("Looking for parameter '%s'...", param);
01105
01106
01107 path.clear();
01108 path.push_back("meta");
01109 path.push_back(param);
01110
01111 dictionary_t data;
01112 parent->getContainerDictionary(path, data);
01113
01114
01115 pset[param] =
01116 objtree::property_t(getRequiredValue(data, param));
01117 }
01118
01119
01120 pset["width"] = objtree::property_t(getStringValue(width).c_str());
01121 pset["height"] = objtree::property_t(getStringValue(height).c_str());
01122
01123
01124 updateScriptParameters(map, parent_id, pset, stream);
01125 }
01126
01127
01128
01129 };
01130