mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 13:06:59 -04:00
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:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user