#ifndef BUILTIN_H #define BUILTIN_H #include #include #include #include #include #include #include #include "strops.h" #include "graphics.h" #include "anyops.h" #include #include #include #include //#define DEVELOPER_MESSAGES false using namespace std; using namespace boost; vector types = { "int", "float", "string", "bool", "void", "null", "Sprite", "Vec2", "Text" }; unordered_map>> builtinFunctionValues; unordered_map builtinVarVals; class NullType { public: string type = "NULL"; }; boost::any nullType; float clamp(float v, float min, float max) { if (v < min) return min; if (v > max) return max; return v; } float lerp(float a, float b, float f) { return a + f * (b - a); } int LogWarning(const string& warningText) { cout << "\x1B[33mWARNING: " << warningText << "\033[0m\t\t" << endl; return 1; } int InterpreterLog(const string& logText) { int Hour = 0; int Min = 0; int Sec = 0; time_t timer = time(0); tm bt{}; #if defined(__unix__) //localtime_r(&timer, &bt); #elif defined(_MSC_VER) localtime_s(&bt, &timer); Hour = bt.tm_hour; Min = bt.tm_min; Sec = bt.tm_sec; #else static mutex mtx; std::lock_guard lock(mtx); bt = *localtime(&timer); #endif cout << "\x1B[34m[" + to_string(Hour) + ":" + to_string(Min) + ":" + to_string(Sec) + "] \x1B[33mZSharp: \x1B[32m" << logText << "\033[0m\t\t" << endl; return 1; } int LogCriticalError(const string& errorText) { int Hour = 0; int Min = 0; int Sec = 0; time_t timer = time(0); tm bt{}; #if defined(__unix__) //localtime_r(&timer, &bt); #elif defined(_MSC_VER) localtime_s(&bt, &timer); Hour = bt.tm_hour; Min = bt.tm_min; Sec = bt.tm_sec; #else static mutex mtx; std::lock_guard lock(mtx); bt = *localtime(&timer); #endif cerr << "\x1B[34m[" + to_string(Hour) + ":" + to_string(Min) + ":" + to_string(Sec) + "] \x1B[33mZSharp: \x1B[31mERROR: " << errorText << "\033[0m\t\t" << endl; exit(EXIT_FAILURE); return 2; } boost::any GetClassSubComponent(boost::any value, string subComponentName) { // If a Sprite Class if (any_type(value) == 4) { return any_cast(value).SubComponent(subComponentName); } // If a Vec2 Class if (any_type(value) == 5) { return any_cast(value).SubComponent(subComponentName); } // If a Text Class if (any_type(value) == 6) { return any_cast(value).SubComponent(subComponentName); } return nullType; } boost::any EditClassSubComponent(boost::any value, string oper, boost::any otherVal, string subComponentName) { // If a Sprite Class if (any_type(value) == 4) { Sprite v = any_cast(value); v.EditSubComponent(subComponentName, oper, otherVal); return v; } // If a Vec2 Class if (any_type(value) == 5) { Vec2 v = any_cast(value); v.EditSubComponent(subComponentName, oper, otherVal); return v; } // If a Text Class if (any_type(value) == 6) { Text t = any_cast(value); t.EditSubComponent(subComponentName, oper, otherVal); return t; } return nullType; } bool AxisAlignedCollision(const Sprite& a, const Sprite& b) // AABB - AABB collision { // collision x-axis? bool collisionX = a.position.x + a.scale.x / 2 >= b.position.x - b.scale.x / 2 && b.position.x + b.scale.x / 2 >= a.position.x - a.scale.x; // collision y-axis? bool collisionY = a.position.y + a.scale.y / 2 >= b.position.y - b.scale.y / 2 && b.position.y + b.scale.y / 2 >= a.position.y - a.scale.y / 2; //// collision x-axis? //bool collisionX = a.position.x - a.scale.x / 2 >= b.position.x + b.scale.x / 2 || // a.position.x + a.scale.x / 2 <= b.position.x - b.scale.x / 2; //// collision y-axis? //bool collisionY = a.position.y - a.scale.y / 2 >= b.position.y + b.scale.y / 2 || // a.position.y + a.scale.y / 2 <= b.position.y - b.scale.y / 2; // collision only if on both axes return collisionX && collisionY; } // Initial script processing, which loads variables and functions from builtin int GetBuiltins(std::string s) { std::string script = replace(s, " ", "\t"); vector lines = split(script, '\n'); vector> words; for (int i = 0; i < (int)lines.size(); i++) { words.push_back(split(lines.at(i), ' ')); } // Go through entire script and iterate through all types to see if line is a // function declaration, then store it with it's value for (int lineNum = 0; lineNum < (int)words.size(); lineNum++) { //Checks if it is function if (words.at(lineNum).at(0) == "func") { vector> functionContents; string functName = split(words.at(lineNum).at(1), '(')[0]; #if DEVELOPER_MESSAGES == true InterpreterLog("Load builtin function " + functName + "..."); #endif string args = ""; for (int w = 1; w < (int)words.at(lineNum).size(); w++) // Get all words from the instantiation line: these are the args { args += replace(replace(words.at(lineNum).at(w), "(", " "), ")", ""); } args = replace(args, functName + " ", ""); functionContents.push_back(split(args, ',')); int numOfBrackets = 1; for (int p = lineNum + 2; p < (int)words.size(); p++) { numOfBrackets += countInVector(words.at(p), "{") - countInVector(words.at(p), "}"); if (numOfBrackets == 0) break; functionContents.push_back(removeTabs(words.at(p), 1)); } builtinFunctionValues[functName] = functionContents; //cout << functName << " is \n" << Vec2Str(functionContents) << endl << endl; } else { if (words.at(lineNum).at(0) == "string") { builtinVarVals[words.at(lineNum).at(1)] = StringRaw(words.at(lineNum).at(3)); #if DEVELOPER_MESSAGES == true InterpreterLog("Load builtin variable " + words.at(lineNum).at(1) + "..."); #endif } else if (words.at(lineNum).at(0) == "int") { builtinVarVals[words.at(lineNum).at(1)] = stoi(words.at(lineNum).at(3)); #if DEVELOPER_MESSAGES == true InterpreterLog("Load builtin variable " + words.at(lineNum).at(1) + "..."); #endif } else if (words.at(lineNum).at(0) == "float") { builtinVarVals[words.at(lineNum).at(1)] = stof(words.at(lineNum).at(3)); #if DEVELOPER_MESSAGES == true InterpreterLog("Load builtin variable " + words.at(lineNum).at(1) + "..."); #endif } else if (words.at(lineNum).at(0) == "bool") { builtinVarVals[words.at(lineNum).at(1)] = stob(words.at(lineNum).at(3)); #if DEVELOPER_MESSAGES == true InterpreterLog("Load builtin variable " + words.at(lineNum).at(1) + "..."); #endif } //else // LogWarning("unrecognized type \'" + words[lineNum][0] + "\' on line: " + to_string(lineNum)); } } return 0; } // Executes boost::any ZSFunction(const string& name, const vector& args) { if (name == "ZS.Math.Sin") return sin(AnyAsFloat(args.at(0))); else if (name == "ZS.Math.Cos") return cos(AnyAsFloat(args.at(0))); else if (name == "ZS.Math.Tan") return tan(AnyAsFloat(args.at(0))); else if (name == "ZS.Math.Round") return AnyAsInt(args.at(0)); else if (name == "ZS.Math.Lerp") return lerp(AnyAsFloat(args.at(0)), AnyAsFloat(args.at(1)), AnyAsFloat(args.at(2))); else if (name == "ZS.Math.Abs") return abs(AnyAsFloat(args.at(0))); else if (name == "ZS.Graphics.Init") { #if DEVELOPER_MESSAGES == true InterpreterLog("Init graphics"); #endif initGraphics(StringRaw(AnyAsString(args.at(0))), AnyAsInt(args.at(1)), AnyAsInt(args.at(2))); } else if (name == "ZS.Graphics.Sprite") { Sprite s(StringRaw(AnyAsString(args.at(0))), any_cast(args.at(1)), any_cast(args.at(2)), AnyAsFloat(args.at(3))); return s; } else if (name == "ZS.Graphics.Draw") any_cast(args.at(0)).Draw(); else if (name == "ZS.Graphics.Load") any_cast(args.at(0)).Load(); else if (name == "ZS.Graphics.Text") { Text t(StringRaw(AnyAsString(args.at(0))), StringRaw(AnyAsString(args.at(1))), any_cast(args.at(2)), AnyAsFloat(args.at(3)), AnyAsFloat(args.at(4)), (Uint8)AnyAsFloat(args.at(5)), (Uint8)AnyAsFloat(args.at(6)), (Uint8)AnyAsFloat(args.at(7))); return t; } else if (name == "ZS.Graphics.DrawText") any_cast(args.at(0)).Draw(); else if (name == "ZS.Graphics.LoadText") any_cast(args.at(0)).Load(); else if (name == "ZS.Physics.AxisAlignedCollision") { return AxisAlignedCollision(any_cast(args.at(0)), any_cast(args.at(1))); } else if (name == "ZS.Input.GetKey") return KEYS[StringRaw(any_cast(args.at(0)))] == 1; else if (name == "ZS.System.Print") cout << StringRaw(AnyAsString(args.at(0))); else if (name == "ZS.System.PrintLine") cout << StringRaw(AnyAsString(args.at(0))) << endl; else if (name == "ZS.System.Vec2") { Vec2 v(AnyAsFloat(args.at(0)), AnyAsFloat(args.at(1))); return v; } else LogWarning("ZS function \'" + name + "\' does not exist."); return nullType; } #endif