Choice rendering now uses "style.image()" instead of "style.choice_images[value]";

Added script functions for working with multiple choice values;
Added in_context support for filter_rule;
Optimized toUpper/toLower because they are slow on windows (they use thread local storage and mutexes)

git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@427 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
twanvl
2007-06-17 13:13:56 +00:00
parent 59d0aee4e7
commit 97e0e8d6d6
16 changed files with 325 additions and 49 deletions
+8 -2
View File
@@ -26,11 +26,14 @@ String ValueAction::getName(bool to_undo) const {
/// Swap the value in a Value object with a new one
inline void swap_value(ChoiceValue& a, ChoiceValue ::ValueType& b) { swap(a.value, b); }
inline void swap_value(MultipleChoiceValue& a, MultipleChoiceValue::ValueType& b) { swap(a.value, b); }
inline void swap_value(ColorValue& a, ColorValue ::ValueType& b) { swap(a.value, b); }
inline void swap_value(ImageValue& a, ImageValue ::ValueType& b) { swap(a.filename, b); a.last_update.update(); }
inline void swap_value(SymbolValue& a, SymbolValue ::ValueType& b) { swap(a.filename, b); a.last_update.update(); }
inline void swap_value(TextValue& a, TextValue ::ValueType& b) { swap(a.value, b); a.last_update.update(); }
inline void swap_value(MultipleChoiceValue& a, MultipleChoiceValue::ValueType& b) {
swap(a.value, b.value);
swap(a.last_change, b.last_change);
}
/// A ValueAction that swaps between old and new values
template <typename T, bool ALLOW_MERGE>
@@ -62,10 +65,13 @@ class SimpleValueAction : public ValueAction {
};
ValueAction* value_action(const ChoiceValueP& value, const Defaultable<String>& new_value) { return new SimpleValueAction<ChoiceValue, true> (value, new_value); }
ValueAction* value_action(const MultipleChoiceValueP& value, const Defaultable<String>& new_value) { return new SimpleValueAction<MultipleChoiceValue, false>(value, new_value); }
ValueAction* value_action(const ColorValueP& value, const Defaultable<Color>& new_value) { return new SimpleValueAction<ColorValue, true> (value, new_value); }
ValueAction* value_action(const ImageValueP& value, const FileName& new_value) { return new SimpleValueAction<ImageValue, false>(value, new_value); }
ValueAction* value_action(const SymbolValueP& value, const FileName& new_value) { return new SimpleValueAction<SymbolValue, false>(value, new_value); }
ValueAction* value_action(const MultipleChoiceValueP& value, const Defaultable<String>& new_value, const String& last_change) {
MultipleChoiceValue::ValueType v = { new_value, last_change };
return new SimpleValueAction<MultipleChoiceValue, false>(value, v);
}
// ----------------------------------------------------------------------------- : Text
+1 -1
View File
@@ -45,7 +45,7 @@ class ValueAction : public Action {
/// Action that updates a Value to a new value
ValueAction* value_action(const ChoiceValueP& value, const Defaultable<String>& new_value);
ValueAction* value_action(const MultipleChoiceValueP& value, const Defaultable<String>& new_value);
ValueAction* value_action(const MultipleChoiceValueP& value, const Defaultable<String>& new_value, const String& last_change);
ValueAction* value_action(const ColorValueP& value, const Defaultable<Color>& new_value);
ValueAction* value_action(const ImageValueP& value, const FileName& new_value);
ValueAction* value_action(const SymbolValueP& value, const FileName& new_value);
+30
View File
@@ -179,6 +179,35 @@ ChoiceStyle::~ChoiceStyle() {
delete thumbnails;
}
void ChoiceStyle::initImage() {
if (image.isSet() || choice_images.empty()) return;
// for, for example:
// choice images:
// a: {uvw}
// b: {xyz}
// generate the script:
// [a: {uvw}, b: {xyz}][input]() or else nil
// or in bytecode
// PUSH_CONST [a: {uvw}, b: {xyz}]
// GET_VAR input
// MEMBER
// CALL 0
// PUSH_CONST nil
// OR_ELSE
// RET
intrusive_ptr<ScriptCustomCollection> lookup(new ScriptCustomCollection());
FOR_EACH(ci, choice_images) {
lookup->key_value[ci.first] = ci.second.getScriptP();
}
Script& script = image.getScript();
script.addInstruction(I_PUSH_CONST, lookup);
script.addInstruction(I_GET_VAR, string_to_variable(_("input")));
script.addInstruction(I_BINARY, I_MEMBER);
script.addInstruction(I_CALL, 0);
script.addInstruction(I_PUSH_CONST, script_nil);
script.addInstruction(I_BINARY, I_OR_ELSE);
script.addInstruction(I_RET);
}
bool ChoiceStyle::update(Context& ctx) {
// Don't update the choice images, leave that to invalidate()
@@ -256,6 +285,7 @@ IMPLEMENT_REFLECTION(ChoiceStyle) {
REFLECT(alignment);
REFLECT(angle);
REFLECT(font);
REFLECT(image);
REFLECT(choice_images);
}
+3
View File
@@ -138,6 +138,7 @@ class ChoiceStyle : public Style {
ChoicePopupStyle popup_style; ///< Style of popups/menus
ChoiceRenderStyle render_style; ///< Style of rendering
Font font; ///< Font for drawing text (when RENDER_TEXT)
ScriptableImage image; ///< Image to draw (when RENDER_IMAGE)
map<String,ScriptableImage> choice_images; ///< Images for the various choices (when RENDER_IMAGE)
bool choice_images_initialized;
Scriptable<String> mask_filename; ///< Filename of an additional mask over the images
@@ -150,6 +151,8 @@ class ChoiceStyle : public Style {
/// Load the mask image, if it's not already done
void loadMask(Package& pkg);
/// Initialize image from choice_images
void initImage();
virtual bool update(Context&);
virtual void initDependencies(Context&, const Dependency&) const;
+43
View File
@@ -48,6 +48,14 @@ IMPLEMENT_REFLECTION_NAMELESS(MultipleChoiceValue) {
REFLECT_BASE(ChoiceValue);
}
bool MultipleChoiceValue::update(Context& ctx) {
String old_value = value();
ctx.setVariable(_("last change"), to_script(last_change));
ChoiceValue::update(ctx);
normalForm();
return value() != old_value;
}
void MultipleChoiceValue::get(vector<String>& out) const {
// split the value
out.clear();
@@ -66,3 +74,38 @@ void MultipleChoiceValue::get(vector<String>& out) const {
}
}
}
void MultipleChoiceValue::normalForm() {
String& val = value.mutateDontChangeDefault();
// which choices are active?
vector<bool> seen(field().choices->lastId());
for (size_t pos = 0 ; pos < val.size() ; ) {
if (val.GetChar(pos) == _(' ')) {
++pos; // ingore whitespace
} else {
// does this choice match the one asked about?
size_t end = val.find_first_of(_(','), pos);
if (end == String::npos) end = val.size();
// find this choice
for (size_t i = 0 ; i < seen.size() ; ++i) {
if (is_substr(val, pos, field().choices->choiceName((int)i))) {
seen[i] = true;
break;
}
}
pos = end + 1;
}
}
// now put them back in the right order
val.clear();
for (size_t i = 0 ; i < seen.size() ; ++i) {
if (seen[i]) {
if (!val.empty()) val += _(", ");
val += field().choices->choiceName((int)i);
}
}
// empty choice name
if (val.empty()) {
val = field().empty_choice;
}
}
+12 -1
View File
@@ -57,13 +57,24 @@ class MultipleChoiceValue : public ChoiceValue {
inline MultipleChoiceValue(const MultipleChoiceFieldP& field) : ChoiceValue(field, true) {}
DECLARE_HAS_FIELD(MultipleChoice);
String last_choice; ///< Which of the choices was selected/deselected last?
String last_change; ///< Which of the choices was selected/deselected last?
// for SimpleValueAction
struct ValueType {
ChoiceValue::ValueType value;
String last_change;
};
/// Splits the value, stores the selected choices in the out parameter
void get(vector<String>& out) const;
virtual bool update(Context&);
private:
DECLARE_REFLECTION();
/// Put the value in normal form (all choices ordered, empty_name
void normalForm();
};
// ----------------------------------------------------------------------------- : Utilities