void C4MapScriptMatTexMask::Init(const C4Value &spec) { // Mask may be initialized by a simple string or by an array of strings, of which the effects are OR'ed const C4ValueArray *arr = spec.getArray(); if (arr) { // Init by array for (int32_t i=0; i<arr->GetSize(); ++i) { C4String *smask = arr->GetItem(i).getStr(); if (!smask) throw C4AulExecError(FormatString("MatTexMask expected string as %dth element in array.", (int)i).getData()); UnmaskSpec(smask); } } else { // Init by string C4String *smask = spec.getStr(); if (smask) UnmaskSpec(smask); else { if (spec) throw C4AulExecError("MatTexMask expected string or array of strings."); // nil defaults to everything except index zero unmasked sky_mask = std::vector<bool>(256, true); tunnel_mask = std::vector<bool>(256, true); sky_mask[0] = false; tunnel_mask[0] = false; } } }
bool C4MapScriptAlgo::GetXYProps(const C4PropList *props, C4PropertyName k, int32_t *out_xy, bool zero_defaults) { // Evaluate property named "k" in proplist props to store two numbers in out_xy: // If props->k is a single integer, fill both numbers in out_xy with it // If props->k is an array, check that it contains two numbers and store them in out_xy if (!props->HasProperty(&Strings.P[k])) { if (zero_defaults) out_xy[0] = out_xy[1] = 0; return false; } C4Value val; C4ValueArray *arr; props->GetProperty(k, &val); if ((arr = val.getArray())) { if (arr->GetSize() != 2) throw C4AulExecError(FormatString("C4MapScriptAlgo: Expected either integer or array with two integer elements in property \"%s\".", Strings.P[k].GetCStr()).getData()); out_xy[0] = arr->GetItem(0).getInt(); out_xy[1] = arr->GetItem(1).getInt(); } else { out_xy[0] = out_xy[1] = val.getInt(); } return true; }
void C4ParticleProperties::SetCollisionFunc(const C4Value &source) { C4ValueArray *valueArray; if (!(valueArray = source.getArray())) return; int arraySize = valueArray->GetSize(); if (arraySize < 1) return; int type = (*valueArray)[0].getInt(); switch (type) { case C4PC_Die: collisionCallback = &C4ParticleProperties::CollisionDie; break; case C4PC_Bounce: collisionCallback = &C4ParticleProperties::CollisionBounce; bouncyness = 1.f; if (arraySize >= 2) bouncyness = ((float)(*valueArray)[1].getInt()); break; case C4PC_Stop: collisionCallback = &C4ParticleProperties::CollisionStop; break; default: assert(false); break; } }
void C4ParticleValueProvider::Set(const C4Value &value) { C4ValueArray *valueArray= value.getArray(); if (valueArray != 0) Set(*valueArray); else Set((float)value.getInt()); }
void C4ParticleValueProvider::SetParameterValue(int type, const C4Value &value, float C4ParticleValueProvider::*floatVal, int C4ParticleValueProvider::*intVal, size_t keyFrameIndex) { // just an atomic data type if (value.GetType() == C4V_Int) { if (type == VAL_TYPE_FLOAT) this->*floatVal = (float)value.getInt(); else if (type == VAL_TYPE_INT) this->*intVal = value.getInt(); else if (type == VAL_TYPE_KEYFRAMES) this->keyFrames[keyFrameIndex] = (float)value.getInt(); } else if (value.GetType() == C4V_Array) { // might be another value provider! C4ParticleValueProvider *child = new C4ParticleValueProvider(); childrenValueProviders.push_back(child); child->Set(*value.getArray()); child->typeOfValueToChange = type; if (type == VAL_TYPE_FLOAT) { child->floatValueToChange = floatVal; } else if (type == VAL_TYPE_INT) { child->intValueToChange = intVal; } else if (type == VAL_TYPE_KEYFRAMES) { child->keyFrameIndex = keyFrameIndex; } } else // invalid { if (type == VAL_TYPE_FLOAT) this->*floatVal = 0.f; else if (type == VAL_TYPE_INT) this->*intVal = 0; else if (type == VAL_TYPE_KEYFRAMES) this->keyFrames[keyFrameIndex] = 0.f; } }
C4MapScriptAlgoModifier::C4MapScriptAlgoModifier(const C4PropList *props, int32_t min_ops, int32_t max_ops) { // Evaluate "Op" property of all algos that take another algo or layer as an operand // Op may be a proplist or an array of proplists C4Value vops; int32_t n; C4ValueArray temp_ops; props->GetProperty(P_Op, &vops); C4ValueArray *ops = vops.getArray(); if (!ops) { C4PropList *op = vops.getPropList(); if (op) { temp_ops.SetItem(0, vops); ops = &temp_ops; n = 1; } } else { n = ops->GetSize(); } if (!ops || n<min_ops || (max_ops && n>max_ops)) throw C4AulExecError(FormatString("C4MapScriptAlgo: Expected between %d and %d operands in property \"Op\".", (int)min_ops, (int)max_ops).getData()); operands.resize(n); try { // can easily crash this by building a recursive prop list // unfortunately, protecting against that is not trivial for (int32_t i=0; i<n; ++i) { C4MapScriptAlgo *new_algo = FnParAlgo(ops->GetItem(i).getPropList()); if (!new_algo) throw C4AulExecError(FormatString("C4MapScriptAlgo: Operand %d in property \"Op\" not valid.", (int)i).getData()); operands[i] = new_algo; } } catch (...) { Clear(); throw; } }