mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 04:57:00 -04:00
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:
@@ -25,8 +25,6 @@ class DependencyDummy : public ScriptIterator {
|
|||||||
virtual ScriptType type() const { return SCRIPT_DUMMY; }
|
virtual ScriptType type() const { return SCRIPT_DUMMY; }
|
||||||
virtual String typeName() const { return _("dummy"); }
|
virtual String typeName() const { return _("dummy"); }
|
||||||
virtual ScriptValueP next() { return ScriptValueP(); }
|
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);
|
ScriptValueP dependency_dummy(new DependencyDummy);
|
||||||
@@ -52,6 +50,9 @@ class DependencyUnion : public ScriptValue {
|
|||||||
virtual ScriptValueP makeIterator() const {
|
virtual ScriptValueP makeIterator() const {
|
||||||
return unified(a->makeIterator(), b->makeIterator());
|
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:
|
private:
|
||||||
ScriptValueP a, b;
|
ScriptValueP a, b;
|
||||||
};
|
};
|
||||||
@@ -212,8 +213,7 @@ ScriptValueP Context::dependencies(const Dependency& dep, const Script& script)
|
|||||||
// Get an object member (almost as normal)
|
// Get an object member (almost as normal)
|
||||||
case I_MEMBER_C: {
|
case I_MEMBER_C: {
|
||||||
String name = *script.constants[i.data];
|
String name = *script.constants[i.data];
|
||||||
stack.back()->signalDependent(*this, dep, name); // dependency on member
|
stack.back() = stack.back()->dependencyMember(name, dep); // dependency on member
|
||||||
stack.back() = stack.back()->getMember(name);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Loop over a container, push next value or jump (almost as normal)
|
// 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;
|
break;
|
||||||
case I_MEMBER: {
|
case I_MEMBER: {
|
||||||
String name = *b;
|
String name = *b;
|
||||||
a->signalDependent(*this, dep, name); // dependency on member
|
a = a->dependencyMember(name, dep); // dependency on member
|
||||||
a = a->getMember(name);
|
|
||||||
break;
|
break;
|
||||||
} case I_ADD:
|
} case I_ADD:
|
||||||
unify(a, b); // may be function composition
|
unify(a, b); // may be function composition
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ ScriptImageP ScriptableImage::update(Context& ctx, Package& pkg, UInt width, UIn
|
|||||||
bool ScriptableImage::upToDate(Context& ctx, Age age) const {
|
bool ScriptableImage::upToDate(Context& ctx, Age age) const {
|
||||||
try {
|
try {
|
||||||
WITH_DYNAMIC_ARG(last_update_age, age.get());
|
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) {
|
} catch (Error e) {
|
||||||
return true; // script gives errors, don't update
|
return true; // script gives errors, don't update
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,6 +78,15 @@ Context& ScriptManager::getContext(const StyleSheetP& stylesheet) {
|
|||||||
return *ctx;
|
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) {
|
void ScriptManager::initDependencies(Context& ctx, Game& game) {
|
||||||
if (game.dependencies_initialized) return;
|
if (game.dependencies_initialized) return;
|
||||||
@@ -115,7 +124,7 @@ void ScriptManager::onAction(const Action& action, bool undone) {
|
|||||||
void ScriptManager::updateStyles(const CardP& card) {
|
void ScriptManager::updateStyles(const CardP& card) {
|
||||||
// lastUpdatedCard = card;
|
// lastUpdatedCard = card;
|
||||||
StyleSheetP stylesheet = set.stylesheetFor(card);
|
StyleSheetP stylesheet = set.stylesheetFor(card);
|
||||||
Context& ctx = getContext(stylesheet);
|
Context& ctx = getContext(card);
|
||||||
// update all styles
|
// update all styles
|
||||||
FOR_EACH(s, stylesheet->card_style) {
|
FOR_EACH(s, stylesheet->card_style) {
|
||||||
if (s->update(ctx)) {
|
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
|
Age starting_age; // the start of the update process
|
||||||
deque<ToUpdate> to_update;
|
deque<ToUpdate> to_update;
|
||||||
// execute script for initial changed value
|
// execute script for initial changed value
|
||||||
value.update(getContext(set.stylesheetFor(card)));
|
value.update(getContext(card));
|
||||||
// update dependent scripts
|
// update dependent scripts
|
||||||
alsoUpdate(to_update, value.fieldP->dependent_scripts, card);
|
alsoUpdate(to_update, value.fieldP->dependent_scripts, card);
|
||||||
updateRecursive(to_update, starting_age);
|
updateRecursive(to_update, starting_age);
|
||||||
@@ -144,7 +153,7 @@ void ScriptManager::updateAll() {
|
|||||||
}
|
}
|
||||||
// update card data of all cards
|
// update card data of all cards
|
||||||
FOR_EACH(card, set.cards) {
|
FOR_EACH(card, set.cards) {
|
||||||
Context& ctx = getContext(set.stylesheetFor(card));
|
Context& ctx = getContext(card);
|
||||||
FOR_EACH(v, card->data) {
|
FOR_EACH(v, card->data) {
|
||||||
v->update(ctx);
|
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) {
|
void ScriptManager::updateToUpdate(const ToUpdate& u, deque<ToUpdate>& to_update, Age starting_age) {
|
||||||
Age age = u.value->last_script_update;
|
Age age = u.value->last_script_update;
|
||||||
if (starting_age < age) return; // this value was already updated
|
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)) {
|
if (u.value->update(ctx)) {
|
||||||
// changed, send event
|
// changed, send event
|
||||||
// ScriptValueEvent change(&*u.card, u.value);
|
// ScriptValueEvent change(&*u.card, u.value);
|
||||||
|
|||||||
@@ -41,7 +41,9 @@ class ScriptManager : public ActionListener {
|
|||||||
~ScriptManager();
|
~ScriptManager();
|
||||||
|
|
||||||
/// Get a context to use for the set, for a given stylesheet
|
/// 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
|
// Update all styles for a particular card
|
||||||
void updateStyles(const CardP& card);
|
void updateStyles(const CardP& card);
|
||||||
@@ -66,8 +68,8 @@ class ScriptManager : public ActionListener {
|
|||||||
|
|
||||||
// Something that needs to be updated
|
// Something that needs to be updated
|
||||||
struct ToUpdate {
|
struct ToUpdate {
|
||||||
Value* value; // value to update
|
Value* value; ///< value to update
|
||||||
CardP card; // card the value is in, or 0 if it is not a card field
|
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.
|
/// Update all things in to_update, and things that depent on them, etc.
|
||||||
/** Only update things that are older than starting_age. */
|
/** Only update things that are older than starting_age. */
|
||||||
|
|||||||
+11
-2
@@ -23,8 +23,8 @@ ScriptValueP ScriptValue::next() { throw InternalEr
|
|||||||
ScriptValueP ScriptValue::makeIterator() const { throw ScriptError( _("Can't convert from ")+typeName()+_(" to collection")); }
|
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")); }
|
int ScriptValue::itemCount() const { throw ScriptError( _("Can't convert from ")+typeName()+_(" to collection")); }
|
||||||
|
|
||||||
void ScriptValue::signalDependent(Context&, const Dependency&, const String& name) {}
|
ScriptValueP ScriptValue::dependencyMember(const String& name, const Dependency&) const { return dependency_dummy; }
|
||||||
ScriptValueP ScriptValue::dependencies(Context&, const Dependency&) const { return dependency_dummy; }
|
ScriptValueP ScriptValue::dependencies(Context&, const Dependency&) const { return dependency_dummy; }
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Iterators
|
// ----------------------------------------------------------------------------- : Iterators
|
||||||
@@ -167,6 +167,15 @@ class ScriptString : public ScriptValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual int itemCount() const { return (int)value.size(); }
|
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:
|
private:
|
||||||
String value;
|
String value;
|
||||||
};
|
};
|
||||||
|
|||||||
+25
-7
@@ -68,9 +68,15 @@ class ScriptValue {
|
|||||||
|
|
||||||
/// Get a member variable from this value
|
/// Get a member variable from this value
|
||||||
virtual ScriptValueP getMember(const String& name) const;
|
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)
|
/// Evaluate this value (if it is a function)
|
||||||
virtual ScriptValueP eval(Context&) const;
|
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()
|
/// Return an iterator for the current collection, an iterator is a value that has next()
|
||||||
virtual ScriptValueP makeIterator() const;
|
virtual ScriptValueP makeIterator() const;
|
||||||
@@ -79,11 +85,6 @@ class ScriptValue {
|
|||||||
/// Return the number of items in this value (assuming it is a collection)
|
/// Return the number of items in this value (assuming it is a collection)
|
||||||
virtual int itemCount() const;
|
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:
|
protected:
|
||||||
/// Delete this object
|
/// Delete this object
|
||||||
@@ -158,7 +159,7 @@ class ScriptCollection : public ScriptValue {
|
|||||||
virtual String typeName() const { return _("collection"); }
|
virtual String typeName() const { return _("collection"); }
|
||||||
virtual ScriptValueP getMember(const String& name) const {
|
virtual ScriptValueP getMember(const String& name) const {
|
||||||
long index;
|
long index;
|
||||||
if (name.ToLong(&index)) {
|
if (name.ToLong(&index) && index >= 0 && (size_t)index < value->size()) {
|
||||||
return toScript(value->at(index));
|
return toScript(value->at(index));
|
||||||
} else {
|
} else {
|
||||||
throw ScriptError(_("Collection has no member ") + name);
|
throw ScriptError(_("Collection has no member ") + name);
|
||||||
@@ -220,14 +221,31 @@ class ScriptObject : public ScriptValue {
|
|||||||
inline ScriptObject(const T& v) : value(v) {}
|
inline ScriptObject(const T& v) : value(v) {}
|
||||||
virtual ScriptType type() const { return SCRIPT_OBJECT; }
|
virtual ScriptType type() const { return SCRIPT_OBJECT; }
|
||||||
virtual String typeName() const { return _("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 {
|
virtual ScriptValueP getMember(const String& name) const {
|
||||||
GetMember gm(name);
|
GetMember gm(name);
|
||||||
gm.handle(*value);
|
gm.handle(*value);
|
||||||
if (gm.result()) return gm.result();
|
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:
|
private:
|
||||||
T value; ///< The object
|
T value; ///< The object
|
||||||
|
ScriptValueP getDefault() const {
|
||||||
|
GetDefaultMember gdm;
|
||||||
|
gdm.handle(*value);
|
||||||
|
return gdm.result();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Creating
|
// ----------------------------------------------------------------------------- : Creating
|
||||||
|
|||||||
@@ -79,7 +79,9 @@ class GetMember : private GetDefaultMember {
|
|||||||
/// Handle an object: we are done if the name matches
|
/// Handle an object: we are done if the name matches
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void handle(const Char* name, const T& object) {
|
void handle(const Char* name, const T& object) {
|
||||||
if (!gdm.result() && name == target_name) gdm.handle(object);
|
if (!gdm.result() && cannocial_name_compare(target_name, name)) {
|
||||||
|
gdm.handle(object);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/// Handle an object: investigate children
|
/// Handle an object: investigate children
|
||||||
template <typename T> void handle(const T&);
|
template <typename T> void handle(const T&);
|
||||||
|
|||||||
Reference in New Issue
Block a user