ScriptObject now looks for a default member for everything that it can not handle, meaning that scripts based on values now work.

git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@72 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
twanvl
2006-11-01 17:54:14 +00:00
parent f18bdafab1
commit ea5be88bdb
7 changed files with 63 additions and 24 deletions
+5 -6
View File
@@ -25,8 +25,6 @@ class DependencyDummy : public ScriptIterator {
virtual ScriptType type() const { return SCRIPT_DUMMY; }
virtual String typeName() const { return _("dummy"); }
virtual ScriptValueP next() { return ScriptValueP(); }
virtual ScriptValueP eval(Context&) const { return dependency_dummy; } // dummy() == dummy
virtual ScriptValueP getMember(const String&) const { return dependency_dummy; } // dummy.* = dummy
};
ScriptValueP dependency_dummy(new DependencyDummy);
@@ -52,6 +50,9 @@ class DependencyUnion : public ScriptValue {
virtual ScriptValueP makeIterator() const {
return unified(a->makeIterator(), b->makeIterator());
}
virtual ScriptValueP dependencyMember(const String& name, const Dependency& dep) const {
return unified(a->dependencyMember(name,dep), b->dependencyMember(name,dep));
}
private:
ScriptValueP a, b;
};
@@ -212,8 +213,7 @@ ScriptValueP Context::dependencies(const Dependency& dep, const Script& script)
// Get an object member (almost as normal)
case I_MEMBER_C: {
String name = *script.constants[i.data];
stack.back()->signalDependent(*this, dep, name); // dependency on member
stack.back() = stack.back()->getMember(name);
stack.back() = stack.back()->dependencyMember(name, dep); // dependency on member
break;
}
// Loop over a container, push next value or jump (almost as normal)
@@ -295,8 +295,7 @@ ScriptValueP Context::dependencies(const Dependency& dep, const Script& script)
break;
case I_MEMBER: {
String name = *b;
a->signalDependent(*this, dep, name); // dependency on member
a = a->getMember(name);
a = a->dependencyMember(name, dep); // dependency on member
break;
} case I_ADD:
unify(a, b); // may be function composition
+1 -1
View File
@@ -123,7 +123,7 @@ ScriptImageP ScriptableImage::update(Context& ctx, Package& pkg, UInt width, UIn
bool ScriptableImage::upToDate(Context& ctx, Age age) const {
try {
WITH_DYNAMIC_ARG(last_update_age, age.get());
return (int)*script.invoke(ctx);
return script_image_up_to_date(script.invoke(ctx));
} catch (Error e) {
return true; // script gives errors, don't update
}
+13 -4
View File
@@ -78,6 +78,15 @@ Context& ScriptManager::getContext(const StyleSheetP& stylesheet) {
return *ctx;
}
}
Context& ScriptManager::getContext(const CardP& card) {
Context& ctx = getContext(set.stylesheetFor(card));
if (card) {
ctx.setVariable(_("card"), toScript(card));
} else {
ctx.setVariable(_("card"), script_nil);
}
return ctx;
}
void ScriptManager::initDependencies(Context& ctx, Game& game) {
if (game.dependencies_initialized) return;
@@ -115,7 +124,7 @@ void ScriptManager::onAction(const Action& action, bool undone) {
void ScriptManager::updateStyles(const CardP& card) {
// lastUpdatedCard = card;
StyleSheetP stylesheet = set.stylesheetFor(card);
Context& ctx = getContext(stylesheet);
Context& ctx = getContext(card);
// update all styles
FOR_EACH(s, stylesheet->card_style) {
if (s->update(ctx)) {
@@ -130,7 +139,7 @@ void ScriptManager::updateValue(Value& value, const CardP& card) {
Age starting_age; // the start of the update process
deque<ToUpdate> to_update;
// execute script for initial changed value
value.update(getContext(set.stylesheetFor(card)));
value.update(getContext(card));
// update dependent scripts
alsoUpdate(to_update, value.fieldP->dependent_scripts, card);
updateRecursive(to_update, starting_age);
@@ -144,7 +153,7 @@ void ScriptManager::updateAll() {
}
// update card data of all cards
FOR_EACH(card, set.cards) {
Context& ctx = getContext(set.stylesheetFor(card));
Context& ctx = getContext(card);
FOR_EACH(v, card->data) {
v->update(ctx);
}
@@ -171,7 +180,7 @@ void ScriptManager::updateRecursive(deque<ToUpdate>& to_update, Age starting_age
void ScriptManager::updateToUpdate(const ToUpdate& u, deque<ToUpdate>& to_update, Age starting_age) {
Age age = u.value->last_script_update;
if (starting_age < age) return; // this value was already updated
Context& ctx = getContext(set.stylesheetFor(u.card));
Context& ctx = getContext(u.card);
if (u.value->update(ctx)) {
// changed, send event
// ScriptValueEvent change(&*u.card, u.value);
+5 -3
View File
@@ -41,7 +41,9 @@ class ScriptManager : public ActionListener {
~ScriptManager();
/// Get a context to use for the set, for a given stylesheet
Context& getContext(const StyleSheetP& s);
Context& getContext(const StyleSheetP&);
/// Get a context to use for the set, for a given card
Context& getContext(const CardP&);
// Update all styles for a particular card
void updateStyles(const CardP& card);
@@ -66,8 +68,8 @@ class ScriptManager : public ActionListener {
// Something that needs to be updated
struct ToUpdate {
Value* value; // value to update
CardP card; // card the value is in, or 0 if it is not a card field
Value* value; ///< value to update
CardP card; ///< card the value is in, or CadP() if it is not a card field
};
/// Update all things in to_update, and things that depent on them, etc.
/** Only update things that are older than starting_age. */
+11 -2
View File
@@ -23,8 +23,8 @@ ScriptValueP ScriptValue::next() { throw InternalEr
ScriptValueP ScriptValue::makeIterator() const { throw ScriptError( _("Can't convert from ")+typeName()+_(" to collection")); }
int ScriptValue::itemCount() const { throw ScriptError( _("Can't convert from ")+typeName()+_(" to collection")); }
void ScriptValue::signalDependent(Context&, const Dependency&, const String& name) {}
ScriptValueP ScriptValue::dependencies(Context&, const Dependency&) const { return dependency_dummy; }
ScriptValueP ScriptValue::dependencyMember(const String& name, const Dependency&) const { return dependency_dummy; }
ScriptValueP ScriptValue::dependencies(Context&, const Dependency&) const { return dependency_dummy; }
// ----------------------------------------------------------------------------- : Iterators
@@ -167,6 +167,15 @@ class ScriptString : public ScriptValue {
}
}
virtual int itemCount() const { return (int)value.size(); }
virtual ScriptValueP getMember(const String& name) const {
// get member returns characters
long index;
if (name.ToLong(&index) && index >= 0 && (size_t)index < value.size()) {
return toScript(String(1,value[index]));
} else {
throw ScriptError(_("String \"") + value + _("\" has no member ") + name);
}
}
private:
String value;
};
+25 -7
View File
@@ -68,9 +68,15 @@ class ScriptValue {
/// Get a member variable from this value
virtual ScriptValueP getMember(const String& name) const;
/// Signal that a script depends on a member of this value
/** It is the abstract version of getMember*/
virtual ScriptValueP dependencyMember(const String& name, const Dependency&) const;
/// Evaluate this value (if it is a function)
virtual ScriptValueP eval(Context&) const;
/// Mark the scripts that this function depends on
/** Return value is an abstract version of the return value of eval */
virtual ScriptValueP dependencies(Context&, const Dependency&) const;
/// Return an iterator for the current collection, an iterator is a value that has next()
virtual ScriptValueP makeIterator() const;
@@ -79,11 +85,6 @@ class ScriptValue {
/// Return the number of items in this value (assuming it is a collection)
virtual int itemCount() const;
/// Signal that a script depends on a member of this value
virtual void signalDependent(Context&, const Dependency&, const String& name);
/// Mark the scripts that this function depends on
/** Return value is an abstract version of the return value of eval */
virtual ScriptValueP dependencies(Context&, const Dependency&) const;
protected:
/// Delete this object
@@ -158,7 +159,7 @@ class ScriptCollection : public ScriptValue {
virtual String typeName() const { return _("collection"); }
virtual ScriptValueP getMember(const String& name) const {
long index;
if (name.ToLong(&index)) {
if (name.ToLong(&index) && index >= 0 && (size_t)index < value->size()) {
return toScript(value->at(index));
} else {
throw ScriptError(_("Collection has no member ") + name);
@@ -220,14 +221,31 @@ class ScriptObject : public ScriptValue {
inline ScriptObject(const T& v) : value(v) {}
virtual ScriptType type() const { return SCRIPT_OBJECT; }
virtual String typeName() const { return _("object"); }
virtual operator String() const { ScriptValueP d = getDefault(); return d ? *d : ScriptValue::operator String(); }
virtual operator double() const { ScriptValueP d = getDefault(); return d ? *d : ScriptValue::operator double(); }
virtual operator int() const { ScriptValueP d = getDefault(); return d ? *d : ScriptValue::operator int(); }
virtual operator Color() const { ScriptValueP d = getDefault(); return d ? *d : ScriptValue::operator Color(); }
virtual ScriptValueP getMember(const String& name) const {
GetMember gm(name);
gm.handle(*value);
if (gm.result()) return gm.result();
else throw ScriptError(_("Object has no member '") + name + _("'"));
else {
// try nameless member
ScriptValueP d = getDefault();
if (d) {
return d->getMember(name);
} else {
throw ScriptError(_("Object has no member '") + name + _("'"));
}
}
}
private:
T value; ///< The object
ScriptValueP getDefault() const {
GetDefaultMember gdm;
gdm.handle(*value);
return gdm.result();
}
};
// ----------------------------------------------------------------------------- : Creating