Added 'position hint' to packages, used to specify the order of the packages in a package list;

Added 'pack type', intended for playtesting (random boosters/starters);
Added 'default(_image)' property to ImageStyle, and added the frame fillers for magic;
Added blurring and bold printing (rather hacky) to the text rendering functions (used for "double click to add image" text);
Added 'symmetric overlay' combine mode, which will look really nice for hybrids;
Moved the watermark choices from the game to an include file in magic-watermarks;
Working on a replacement for the image scripting system that plays nicer with the rest of the code. In particular, it will be possible to compare generated images quickly, so they can be updated continuously. This is a work in progress, currently there are two versions of everything.

git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@327 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
twanvl
2007-05-09 21:41:15 +00:00
parent 6f7db851a7
commit 3c4729aaa2
63 changed files with 964 additions and 134 deletions
+100 -3
View File
@@ -17,7 +17,11 @@
#include <render/symbol/filter.hpp>
#include <gui/util.hpp> // load_resource_image
DECLARE_TYPEOF_COLLECTION(SymbolStyle::VariationP);
#include <gfx/generated_image.hpp>
DECLARE_TYPEOF_COLLECTION(SymbolVariationP);
bool parse_enum(const String&, ImageCombine& out);
// ----------------------------------------------------------------------------- : Macros
@@ -32,6 +36,84 @@ template <> inline ScriptImageP from_script<ScriptImageP>(const ScriptValueP& va
#define SCRIPT_IMAGE_PARAM_UP_TO_DATE(name) script_image_up_to_date(ctx.getVariable(_(#name)))
// ----------------------------------------------------------------------------- : Utility
// TODO : use this system
template <> inline GeneratedImageP from_script<GeneratedImageP>(const ScriptValueP& value) {
return image_from_script(value);
}
// ----------------------------------------------------------------------------- : Image functions
SCRIPT_FUNCTION(linear_blend2) {
SCRIPT_PARAM(GeneratedImageP, image1);
SCRIPT_PARAM(GeneratedImageP, image2);
SCRIPT_PARAM(double, x1); SCRIPT_PARAM(double, y1);
SCRIPT_PARAM(double, x2); SCRIPT_PARAM(double, y2);
return new_intrusive6<LinearBlendImage>(image1, image2, x1,y1, x2,y2);
}
SCRIPT_FUNCTION(masked_blend2) {
SCRIPT_PARAM(GeneratedImageP, light);
SCRIPT_PARAM(GeneratedImageP, dark);
SCRIPT_PARAM(GeneratedImageP, mask);
return new_intrusive3<MaskedBlendImage>(light, dark, mask);
}
SCRIPT_FUNCTION(combine_blend2) {
SCRIPT_PARAM(String, combine);
SCRIPT_PARAM(GeneratedImageP, image1);
SCRIPT_PARAM(GeneratedImageP, image2);
ImageCombine image_combine;
if (!parse_enum(combine, image_combine)) {
throw ScriptError(_("Not a valid combine mode: '") + combine + _("'"));
}
return new_intrusive3<CombineBlendImage>(image1, image2, image_combine);
}
SCRIPT_FUNCTION(set_mask2) {
SCRIPT_PARAM(GeneratedImageP, image);
SCRIPT_PARAM(GeneratedImageP, mask);
return new_intrusive2<SetMaskImage>(image, mask);
}
SCRIPT_FUNCTION(set_combine2) {
SCRIPT_PARAM(String, combine);
SCRIPT_PARAM(GeneratedImageP, input);
ImageCombine image_combine;
if (!parse_enum(combine, image_combine)) {
throw ScriptError(_("Not a valid combine mode: '") + combine + _("'"));
}
return new_intrusive2<SetCombineImage>(input, image_combine);
}
SCRIPT_FUNCTION(symbol_variation2) {
// find symbol
SCRIPT_PARAM(ValueP, symbol);
SymbolValueP value = dynamic_pointer_cast<SymbolValue>(symbol);
SCRIPT_PARAM(String, variation);
// find style
SCRIPT_PARAM(Set*, set);
SCRIPT_OPTIONAL_PARAM_(CardP, card);
SymbolStyleP style = dynamic_pointer_cast<SymbolStyle>(set->stylesheetFor(card)->styleFor(value->fieldP));
if (!style) throw InternalError(_("Symbol value has a style of the wrong type"));
// find variation
FOR_EACH(v, style->variations) {
if (v->name == variation) {
// found it
return new_intrusive3<SymbolToImage>(value->filename, value->last_update, v);
}
}
throw ScriptError(_("Variation of symbol not found ('") + variation + _("')"));
}
SCRIPT_FUNCTION(built_in_image2) {
SCRIPT_PARAM(String, input);
return new_intrusive1<BuiltInImage>(input);
}
// ----------------------------------------------------------------------------- : Image functions
SCRIPT_IMAGE_FUNCTION(linear_blend) {
@@ -62,6 +144,22 @@ SCRIPT_IMAGE_FUNCTION_UP_TO_DATE
);
}
SCRIPT_IMAGE_FUNCTION(combine_blend) {
SCRIPT_PARAM(String, combine);
SCRIPT_PARAM(ScriptImageP, image1);
SCRIPT_PARAM(ScriptImageP, image2);
if (!parse_enum(combine, image1->combine)) {
throw ScriptError(_("Not a valid combine mode: '") + combine + _("'"));
}
combine_image(image1->image, image2->image, image1->combine);
return image1;
SCRIPT_IMAGE_FUNCTION_UP_TO_DATE
SCRIPT_RETURN(
SCRIPT_IMAGE_PARAM_UP_TO_DATE(image1) &&
SCRIPT_IMAGE_PARAM_UP_TO_DATE(image2)
);
}
SCRIPT_IMAGE_FUNCTION(set_mask) {
SCRIPT_PARAM(ScriptImageP, image);
SCRIPT_PARAM(ScriptImageP, mask);
@@ -74,8 +172,6 @@ SCRIPT_IMAGE_FUNCTION_UP_TO_DATE
);
}
bool parse_enum(const String&, ImageCombine& out);
SCRIPT_IMAGE_FUNCTION(set_combine) {
SCRIPT_PARAM(String, combine);
SCRIPT_PARAM(ScriptImageP, input);
@@ -136,6 +232,7 @@ SCRIPT_IMAGE_FUNCTION_UP_TO_DATE
void init_script_image_functions(Context& ctx) {
ctx.setVariable(_("linear blend"), script_linear_blend);
ctx.setVariable(_("masked blend"), script_masked_blend);
ctx.setVariable(_("combine blend"), script_combine_blend);
ctx.setVariable(_("set mask"), script_set_mask);
ctx.setVariable(_("set combine"), script_set_combine);
ctx.setVariable(_("symbol variation"), script_symbol_variation);
+80
View File
@@ -14,6 +14,58 @@
IMPLEMENT_DYNAMIC_ARG(Package*, load_images_from, nullptr);
// ----------------------------------------------------------------------------- : Utility
// convert any script value to a GeneratedImageP
GeneratedImageP image_from_script(const ScriptValueP& value) {
if (value->type() == SCRIPT_STRING) {
return new_intrusive1<PackagedImage>(value->toString());
} else {
GeneratedImageP img = dynamic_pointer_cast<GeneratedImage>(value);
if (!img) throw ScriptError(_ERROR_2_("can't convert", value->typeName(), _TYPE_("image")));
return img;
}
}
// ----------------------------------------------------------------------------- : ScriptableImage2
Image ScriptableImage2::generate(const GeneratedImage::Options& options, bool cache) const {
if (!isReady()) {
// error, return blank image
Image i(1,1);
i.InitAlpha();
i.SetAlpha(0,0,0);
return i;
}
if (cached.Ok() && cached.GetWidth() == options.width && cached.GetHeight() == options.height) {
return cached;
}
Image img = value->generate(options);
if (cache) cached = img;
return img;
}
ImageCombine ScriptableImage2::combine() const {
if (!isReady()) return COMBINE_NORMAL;
return value->combine();
}
bool ScriptableImage2::update(Context& ctx) {
if (!isScripted()) return false;
GeneratedImageP new_value = image_from_script(script.invoke(ctx));
if (!new_value || !value || *new_value != *value) {
value = new_value;
return true;
} else {
return false;
}
}
// ----------------------------------------------------------------------------- : ScriptImage
ScriptType ScriptImage::type() const { return SCRIPT_IMAGE; }
@@ -160,3 +212,31 @@ template <> void Writer::handle(const ScriptableImage& s) {
template <> void GetDefaultMember::handle(const ScriptableImage& s) {
handle(s.script.unparsed);
}
// ----------------------------------------------------------------------------- : Reflection
// we need some custom io, because the behaviour is different for each of Reader/Writer/GetMember
template <> void Reader::handle(ScriptableImage2& s) {
handle(s.script.unparsed);
if (starts_with(s.script.unparsed, _("script:"))) {
s.script.unparsed = s.script.unparsed.substr(7);
s.script.parse(*this);
} else if (s.script.unparsed.find_first_of('{') != String::npos) {
s.script.parse(*this, true);
} else {
// script is a constant function
s.script.script = new_intrusive<Script>();
s.script.script->addInstruction(I_PUSH_CONST, s.script.unparsed);
s.script.script->addInstruction(I_RET);
}
}
template <> void Writer::handle(const ScriptableImage2& s) {
handle(s.script.unparsed);
}
template <> void GetDefaultMember::handle(const ScriptableImage2& s) {
handle(s.script.unparsed);
}
+49 -2
View File
@@ -13,13 +13,60 @@
#include <util/age.hpp>
#include <util/dynamic_arg.hpp>
#include <script/scriptable.hpp>
#include <gfx/gfx.hpp>
//%%#include <gfx/gfx.hpp>
#include <gfx/generated_image.hpp>
class Package;
DECLARE_INTRUSIVE_POINTER_TYPE(ScriptImage);
DECLARE_INTRUSIVE_POINTER_TYPE(ScriptImage); //%% OLD
DECLARE_INTRUSIVE_POINTER_TYPE(GeneratedImage); //%% OLD
// ----------------------------------------------------------------------------- : ScriptableImage
/// An image that can also be scripted
/** Differs from Scriptable<Image> in that:
* - A script is always used
* - Age is checked, chached images are used if possible
* - The image can be scaled
*/
class ScriptableImage2 {
public:
inline ScriptableImage2() {}
inline ScriptableImage2(const String& script) : script(script) {}
/// Is there an image set?
inline bool isScripted() const { return script; }
/// Is there an image generator available?
inline bool isReady() const { return value; }
/// Generate an image.
Image generate(const GeneratedImage::Options& options, bool cache = false) const;
/// How should images be combined with the background?
ImageCombine combine() const;
/// Update the script, returns true if the value has changed
bool update(Context& ctx);
inline void initDependencies(Context& ctx, const Dependency& dep) const {
script.initDependencies(ctx, dep);
}
private:
OptionalScript script; ///< The script, not really optional
GeneratedImageP value; ///< The image generator
mutable Image cached; ///< The cached actual image
DECLARE_REFLECTION();
};
/// Missing for now
inline ScriptValueP to_script(const ScriptableImage2&) { return script_nil; }
/// Convert a script value to a GeneratedImageP
GeneratedImageP image_from_script(const ScriptValueP& value);
// ----------------------------------------------------------------------------- : ScriptableImage
//%% OLD
DECLARE_DYNAMIC_ARG(Package*, load_images_from);
/// An image, returned by a script function