diff --git a/DMS/Connection.h b/DMS/Connection.h new file mode 100644 index 0000000..1fdfcf7 --- /dev/null +++ b/DMS/Connection.h @@ -0,0 +1,42 @@ +#pragma once +#include +#include +namespace multi { + /* + + */ + template + class connection { + // bool = func(void* v) + std::vector funcs; + std::vector _funcs; + public: + int32_t connect(void(*func)(T)) { + funcs.push_back(func); + return funcs.size() - 1; + } + int32_t connect(void(*func)()) { + _funcs.push_back(func); + return (_funcs.size())*-1; + } + void fire(T arg) { + // Calls everything in the funcs and _funcs list + for (auto f : funcs) { + f(arg); + } + fire(); // Get the _funcs list as well + } + void fire() { + // Calls everything in the funcs list only + for (auto f : _funcs) { + f(); + } + } + int32_t operator+=(void(*func)(T)) { + return connect(func); + } + int32_t operator+=(void(*func)()) { + return connect(func); + } + }; +} \ No newline at end of file diff --git a/DMS/DMS.cpp b/DMS/DMS.cpp index 02b1da4..8e5d190 100644 --- a/DMS/DMS.cpp +++ b/DMS/DMS.cpp @@ -1,37 +1,16 @@ +#include +#include +#include #include "pch.h" #include "dms.h" -//#include using namespace dms; -//typedef void(*FNPTR)(); -//using namespace std::chrono; -//value invokeTest(void* self, dms_state* state, dms_args* args) { -// utils::print(args->args[0].getPrintable()); -// return "I work!"; -//} -//value concat(void* self, dms_state* state, dms_args* args) { -// std::stringstream str; -// for (size_t i = 0; i < args->size() - 1; i++) -// str << args->args[i].getPrintable(); -// return value(str.str()); -//} -//void draw(sf::RenderWindow& window) { -// sf::CircleShape shape(60.f); -// shape.setFillColor(sf::Color(150, 50, 250)); -// -// // set a 10-pixel wide orange outline -// shape.setOutlineThickness(10.f); -// shape.setOutlineColor(sf::Color(250, 150, 100)); -// window.draw(shape); -//} int main() { // TODO fix disp cmd to handle the standard - /*milliseconds ms = duration_cast( - system_clock::now().time_since_epoch() - ); + /*milliseconds ms = duration_cast(system_clock::now().time_since_epoch()); utils::print(ms.count());*/ LineParser parser = LineParser("test.dms"); @@ -39,44 +18,430 @@ int main() // Load audio stuff dms::audio::init(state); state->dump(); - state->run(); - - // create the window - //sf::RenderWindow window(sf::VideoMode(800, 600), "My window"); + memory* mem = state->getMem(); + + sf::RenderWindow window(sf::VideoMode(1024, 768, 32), "Background Test"); + + sf::Texture texture; + texture.loadFromFile("background.jpg"); + sf::Sprite sprite; + sf::Vector2u size = texture.getSize(); + sprite.setTexture(texture); + sprite.setOrigin(0, 0); + + sf::Font font; + font.loadFromFile("font.ttf"); + + sf::Text text("Hello this is a test|!", font); + text.setCharacterSize(30); + text.setStyle(sf::Text::Bold); + text.setFillColor(sf::Color::Black); + auto test = text.getGlobalBounds(); + std::cout << test.left << "," << test.top << "," << test.width << "," << test.height << std::endl; + text.setPosition(11, 768 - 110 - (test.height-test.top)); + //std::cout << test << std::endl; + + sf::RectangleShape rectangle; + rectangle.setSize(sf::Vector2f(1004, 100)); + rectangle.setOutlineColor(sf::Color::Red); + rectangle.setOutlineThickness(1); + rectangle.setPosition(10, 768-110); //// run the program as long as the window is open - //while (window.isOpen()) - //{ - // // check all the window's events that were triggered since the last iteration of the loop - // sf::Event event; - // while (window.pollEvent(event)) - // { - // // "close requested" event: we close the window - // if (event.type == sf::Event::Closed) - // window.close(); - // } + while (window.isOpen()) + { + // check all the window's events that were triggered since the last iteration of the loop + sf::Event event; + while (window.pollEvent(event)) + { + // "close requested" event: we close the window + if (event.type == sf::Event::Closed) + window.close(); + } - // // clear the window with black color - // window.clear(sf::Color::Black); + // clear the window with black color + window.clear(sf::Color::Black); - // // draw everything here... - // draw(window); + if (!state->next(mem)) { + // We should clean up some stuff here! + break; + } - // // end the current frame - // window.display(); - //} + // draw everything here... + window.draw(sprite); + window.draw(rectangle); + window.draw(text); - /*HINSTANCE hInst = LoadLibrary(L"C:\\Users\\rayam\\Desktop\\test.dll"); - if (!hInst) { - std::cout << "\nCould not load the library!"; - return EXIT_FAILURE; + // end the current frame + window.display(); + } +} + +/* +#include +#include +#include +#include "pch.h" +#include + + + +struct Box +{ + int x1; + int y1; + int x2; + int y2; +}; + +int win_get_num_video_adapters(void) +{ + DISPLAY_DEVICE dd; + int count = 0; + int c = 0; + + memset(&dd, 0, sizeof(dd)); + dd.cb = sizeof(dd); + + while (EnumDisplayDevices(NULL, count, &dd, 0) != false) { + if (dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) + c++; + count++; } - FNPTR fn = (FNPTR)GetProcAddress(hInst, "_init"); - if (!fn) { - std::cout << "\nCould not load function from library!"; - return EXIT_FAILURE; + return c; +} + +bool win_get_monitor_info(int adapter, Box* info) +{ + DISPLAY_DEVICE dd; + DEVMODE dm; + + memset(&dd, 0, sizeof(dd)); + dd.cb = sizeof(dd); + if (!EnumDisplayDevices(NULL, adapter, &dd, 0)) { + return false; } - fn();*/ -} \ No newline at end of file + memset(&dm, 0, sizeof(dm)); + dm.dmSize = sizeof(dm); + if (!EnumDisplaySettings(dd.DeviceName, ENUM_CURRENT_SETTINGS, &dm)) { + return false; + } + + // ASSERT(dm.dmFields & DM_PELSHEIGHT); + // ASSERT(dm.dmFields & DM_PELSWIDTH); + // Disabled this assertion for now as it fails under Wine 1.2. // + // ASSERT(dm.dmFields & DM_POSITION); // + +info->x1 = dm.dmPosition.x; +info->y1 = dm.dmPosition.y; +info->x2 = info->x1 + dm.dmPelsWidth; +info->y2 = info->y1 + dm.dmPelsHeight; +return true; +} + +struct Rect +{ + int _x; + int _y; + int _w; + int _h; +}; + +BOOL CALLBACK MyInfoEnumProc( + HMONITOR hMonitor, + HDC hdcMonitor, + LPRECT lprcMonitor, + LPARAM dwData +) +{ + MONITORINFOEX mi; + ZeroMemory(&mi, sizeof(mi)); + mi.cbSize = sizeof(mi); + + GetMonitorInfo(hMonitor, &mi); + wprintf(L"DisplayDevice: %s\n", mi.szDevice); + + return TRUE; +} + +sf::View getLetterboxView(sf::View view, int windowWidth, int windowHeight) { + + // Compares the aspect ratio of the window to the aspect ratio of the view, + // and sets the view's viewport accordingly in order to archieve a letterbox effect. + // A new view (with a new viewport set) is returned. + + float windowRatio = windowWidth / (float)windowHeight; + float viewRatio = view.getSize().x / (float)view.getSize().y; + float sizeX = 1; + float sizeY = 1; + float posX = 0; + float posY = 0; + + bool horizontalSpacing = true; + if (windowRatio < viewRatio) + horizontalSpacing = false; + + // If horizontalSpacing is true, the black bars will appear on the left and right side. + // Otherwise, the black bars will appear on the top and bottom. + + if (horizontalSpacing) { + sizeX = viewRatio / windowRatio; + posX = (1 - sizeX) / 2.f; + } + + else { + sizeY = windowRatio / viewRatio; + posY = (1 - sizeY) / 2.f; + } + + view.setViewport(sf::FloatRect(posX, posY, sizeX, sizeY)); + + return view; +} + +void getRectMonitor(HWND hwnd, Rect& rect) +{ + HMONITOR hMonitor; + MONITORINFO mInfo; + + hMonitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); + + mInfo.cbSize = sizeof(mInfo); + + GetMonitorInfo(hMonitor, &mInfo); + + rect._x = mInfo.rcMonitor.left; + rect._y = mInfo.rcMonitor.top; + rect._w = mInfo.rcMonitor.right - mInfo.rcMonitor.left; + rect._h = mInfo.rcMonitor.bottom - mInfo.rcMonitor.top; + +} + +void showMonitorInfo(HWND hwnd) +{ + Rect rectMonitor; + getRectMonitor(hwnd, rectMonitor); + std::cout << "--- MONITOR INFOS ---\n"; + std::cout << " Position : " << rectMonitor._x << " , " << rectMonitor._y << " \n"; + std::cout << " Size : " << rectMonitor._w << " , " << rectMonitor._h << " \n"; + std::cout << "----------------------\n"; + +} + +BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) +{ + int* Count = (int*)dwData; + (*Count)++; + return TRUE; +} + +int MonitorCount() +{ + int Count = 0; + if (EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&Count)) + return Count; + return -1;//signals an error +} + + +int main() +{ + unsigned screenW = 960; + unsigned screenH = 540; + + sf::RenderWindow window; + window.create(sf::VideoMode(screenW, screenH), "My window", sf::Style::Default); + HWND hwnd = window.getSystemHandle(); + + sf::Event event; + + sf::Texture texture; + texture.loadFromFile("bg.png"); + sf::Sprite sprite(texture); + + sf::View view; + view.setSize(screenW, screenH); + view.setCenter(view.getSize().x / 2, view.getSize().y / 2); + view = getLetterboxView(view, screenW, screenH); + + sf::CircleShape shape(10.f); + shape.setFillColor(sf::Color::Green); + + sf::RectangleShape rectView(sf::Vector2f(screenW, screenH)); + rectView.setFillColor(sf::Color(40, 60, 80)); + + bool isFullScreen = false; + bool keyFull = false; + bool keyTab = false; + bool keyShow = false; + + DISPLAY_DEVICE dd; + dd.cb = sizeof(dd); + int deviceIndex = 0; + int monitorIndex = 0; + + while (EnumDisplayDevices(0, deviceIndex, &dd, 0)) + { + while (EnumDisplayDevices(dd.DeviceName, monitorIndex, &dd, 0)) + { + std::cout << dd.DeviceName << ", " << dd.DeviceString << "\n"; + + ++monitorIndex; + } + ++deviceIndex; + } + + + std::cout << "nb Monitor = " << MonitorCount() << "\n"; + + float x = 10; + window.setFramerateLimit(60); + + + sf::Vector2i pos = sf::Vector2i(screenW / 2, screenH / 2); + + + showMonitorInfo(hwnd); + + sf::Vector2i savePos; + savePos.x = 0; + savePos.y = 0; + + int currentMonitor = 0; + + while (window.isOpen()) + { + if (!isFullScreen) + { + sf::Vector2i winPos = window.getPosition(); + savePos.x = winPos.x; + savePos.y = winPos.y; + } + + + // on inspecte tous les évènements de la fenêtre qui ont été émis depuis la précédente itération + while (window.pollEvent(event)) + { + // évènement "fermeture demandée" : on ferme la fenêtre + if (event.type == sf::Event::Closed) + window.close(); + + if (event.type == sf::Event::Resized) + view = getLetterboxView(view, event.size.width, event.size.height); + } + + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) window.close(); + + if (!sf::Keyboard::isKeyPressed(sf::Keyboard::Space)) keyFull = false; + + + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space) && !keyFull) + { + keyFull = true; + + isFullScreen = !isFullScreen; + + if (isFullScreen) + { + std::cout << "FULLSCREEN \n"; + + Rect rectM; + getRectMonitor(hwnd, rectM); + + //showMonitorInfo(hwnd); + + std::cout << "rectM = " << rectM._x << " , " << rectM._y; + std::cout << " | " << rectM._w << " , " << rectM._h << "\n"; + + window.create(sf::VideoMode(rectM._w, rectM._h), "My window", sf::Style::None); + hwnd = window.getSystemHandle(); + + window.setPosition(sf::Vector2i(rectM._x, rectM._y)); + window.setSize(sf::Vector2u(rectM._w, rectM._h)); + + SetWindowPos(hwnd, HWND_TOPMOST, + 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, + SWP_NOMOVE | SWP_NOSIZE); + + //window.setFramerateLimit(60); + window.setVerticalSyncEnabled(true); + view = getLetterboxView(view, rectM._w, rectM._h); + window.setView(sf::View(sf::FloatRect(0, 0, rectM._w, rectM._h))); + + } + else + { + std::cout << "WINDOWED \n"; + + window.create(sf::VideoMode(screenW, screenH), "My window", sf::Style::Default); + hwnd = window.getSystemHandle(); + window.setPosition(savePos); + + window.setFramerateLimit(60); + view = getLetterboxView(view, screenW, screenH); + } + + + } + + if (!sf::Keyboard::isKeyPressed(sf::Keyboard::Tab)) keyTab = false; + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Tab) && !keyTab) + { + keyTab = true; + + std::cout << "Switch Monitor !\n"; + + ++currentMonitor; + + if (currentMonitor > win_get_num_video_adapters() - 1) + currentMonitor = 0; + + std::cout << " Current Monitor = " << currentMonitor << "\n"; + + } + + if (!sf::Keyboard::isKeyPressed(sf::Keyboard::S)) keyShow = false; + if (sf::Keyboard::isKeyPressed(sf::Keyboard::S) && !keyShow) + { + keyShow = true; + showMonitorInfo(hwnd); + } + + float v = 1; + + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) pos.y += -v; + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) pos.y += v; + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) pos.x += -v; + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) pos.x += v; + + + x += 1; + + if (x > screenW) + x = 0; + + //pos = sf::Mouse::getPosition(window); + + + + shape.setPosition(pos.x, pos.y); + + sprite.setPosition(x, 0); + + window.setView(view); + + window.clear(); + + window.draw(rectView); + window.draw(sprite); + window.draw(shape); + + window.display(); + + } + + return 0; +} +*/ \ No newline at end of file diff --git a/DMS/DMS.vcxproj b/DMS/DMS.vcxproj index 74f1dd9..d996c82 100644 --- a/DMS/DMS.vcxproj +++ b/DMS/DMS.vcxproj @@ -190,13 +190,16 @@ + + + @@ -214,6 +217,7 @@ + diff --git a/DMS/DMS.vcxproj.filters b/DMS/DMS.vcxproj.filters index 16ade1f..d9f4329 100644 --- a/DMS/DMS.vcxproj.filters +++ b/DMS/DMS.vcxproj.filters @@ -43,12 +43,15 @@ {978b41cd-27e4-4b8c-874e-3b6e927b3d4d} - - {39dc0943-16ca-48a6-b04e-04ba994cfb8d} - {ef57bfaf-35f9-4b3e-8642-7ee96fb82139} + + {b3c47fc7-ce47-46c5-86b4-827acf0bcbbb} + + + {584d8d2d-e56e-4a89-a1fe-08a13c3d08a9} + @@ -117,6 +120,9 @@ Source Files\DMS\platformdep + + Source Files\DMS\platformdep + @@ -185,8 +191,17 @@ Header Files\DMS + + Header Files\multi + + + Header Files\DMS\libraries + - Header Files\DMS\platformdep + Header Files\DMS\libraries + + + Header Files\DMS\libraries \ No newline at end of file diff --git a/DMS/LineParserMatchProcess.cpp b/DMS/LineParserMatchProcess.cpp index 21d4df2..5b81890 100644 --- a/DMS/LineParserMatchProcess.cpp +++ b/DMS/LineParserMatchProcess.cpp @@ -940,7 +940,13 @@ namespace dms { if (stream->match(cbracketo)) { size_t last_line = stream->last().line_num; std::vector t = stream->next(cbracketo, cbracketc); // Consume and get tokens - t.pop_back(); + if (t.size() == 1) { + t.pop_back(); + t.push_back(token{tokens::newline}); + } + else { + t.pop_back(); + } tokenstream tempstream(&t); if (notBalanced(t, last_line, stream, "{", "}")) return false; diff --git a/DMS/LineParserParse.cpp b/DMS/LineParserParse.cpp index c40d664..3397608 100644 --- a/DMS/LineParserParse.cpp +++ b/DMS/LineParserParse.cpp @@ -457,9 +457,7 @@ namespace dms { for (size_t i = 0; i < tokens.size() - 1; i++) {//The lase symbol is parac since that was the consume condition if (tokens[i].type == tokens::name) { // We got a name which is refering to a variable so lets build one - value v; - v.type = datatypes::variable; // Special type, it writes data to the string portion, but is interperted as a lookup - v.getString() = tokens[i].name; + value v(tokens[i].name, datatypes::variable); args.push(v); } else if (tokens[i].type == tokens::seperator) { @@ -475,6 +473,10 @@ namespace dms { } // If all went well the 'args' now has all of tha params for the method we will be working with current_chunk->params = args; + for (size_t i = 0; i < args.size(); i++) { + current_chunk->cmds.back()->args.push(args.args[i]); + } + // Thats should be all we need to do if (stream->peek().type != tokens::bracketc) { state->push_error(errors::error{ errors::badtoken, "Incomplete function block declaration! Expected ']' to close the block!",true,line,current_chunk }); diff --git a/DMS/background.jpg b/DMS/background.jpg new file mode 100644 index 0000000..b0f8b80 Binary files /dev/null and b/DMS/background.jpg differ diff --git a/DMS/codes.h b/DMS/codes.h index 10977de..d2cde3e 100644 --- a/DMS/codes.h +++ b/DMS/codes.h @@ -17,7 +17,7 @@ namespace dms { CHOI, // Done BLCK, // CHAR, // Done - WHLE, + WHLE, // Scraped FUNC, // Done IFFF, // Done KNOT, // Done @@ -29,9 +29,9 @@ namespace dms { JMPZ, // Scraped see [COMP] INST, // Done ERRO, - GOTO, + GOTO, // Done JUMP, // Done - RETN, + RETN, // Done EXIT, // Done DEBG, DSPD, // Todo @@ -48,7 +48,7 @@ namespace dms { LIST, // Done LINE, // Done HALT, // Todo - FILE, + FILE, // Done GC, ASID, // Done OFUN // Done diff --git a/DMS/dms_state.h b/DMS/dms_state.h index c6654b6..a117281 100644 --- a/DMS/dms_state.h +++ b/DMS/dms_state.h @@ -36,6 +36,7 @@ namespace dms { double Sversion; // The version of errors::error err; character* speaker = nullptr; + dms_state(); void dump(std::string fn = "dump.bin"); @@ -68,6 +69,7 @@ namespace dms { void pushMem(); void popMem(); bool run(); + bool next(memory* mem); bool run(std::string ent,memory* mem); bool run(std::string instance); bool error(std::string); @@ -77,6 +79,17 @@ namespace dms { private: // From what I gathered //std::mutex memory_mutex; + + // Next links + codes::op n_code; + cmd* n_c = nullptr; + bool n_halt = false; + size_t n_pos = 0; + size_t n_max = 0; + std::vector n_cmds; + size_t n_ln = 0; + std::string n_temp; + // void pushMem(memory&); bool stop = false; bool init_init = false; diff --git a/DMS/dms_state_interpret.cpp b/DMS/dms_state_interpret.cpp index 1130da4..e1023c7 100644 --- a/DMS/dms_state_interpret.cpp +++ b/DMS/dms_state_interpret.cpp @@ -643,7 +643,512 @@ namespace dms { break; } } + + return true; + } + bool dms_state::next(memory* mem) { + if (n_halt || stop) + return false; + if (!n_cmds.size()) + init(chunks["$INIT"], n_pos, n_max, n_cmds); + n_c = n_cmds[n_pos++]; + n_code = n_c->opcode; + //debug("(",pos,")> ",*c); + //wait(); + switch (n_code) + { + // Handle flags here + case ENTR: + // When reading code from a file the flags are compiled and we need to load them + entry = n_c->args.args[0].getPrintable(); + break; + case ENAB: + enable(n_c->args.args[0].getPrintable()); + break; + case DISA: + disable(n_c->args.args[0].getPrintable()); + break; + case codes::FILE: + cur_file = n_c->args.args[0].getPrintable(); + case LOAD: + // Nothing needs to be done here + break; + case VERN: + Sversion = n_c->args.args[0].n; + // Version X.xx + // X: Will not guarantee compatibality. Code breaking changes should be expected especially on lower versions + // xx: Will not break compatibality. They may add features as it goes up the ranks, but those changes do not break older code. If they do they will increase the X part and not the xx part + if (Sversion > Iversion) { + push_error(errors::error{ errors::incompatible_version ,"This script was made for a later version of this interperter!" }); + return false; + } + else if ((int)Iversion > (int)(Sversion)) { + push_warning(errors::error{ errors::incompatible_version ,"This script was made for an older version of this interperter, some features might not work!" }); + } + break; + case USIN: + // How we add modules into the code. This is the code that actually loads that data! + break; + // Flags handled + case EXIT: + if (n_c->args.args.size()) { + exitcode = (int)n_c->args.args[0].n; + } + return true; + break; + case KNOT: + { + value cmp = n_c->args.args[0]; + if (cmp.resolve(this).type == datatypes::boolean || cmp.resolve(this).isNil()) { + if (!cmp.resolve(this).b || cmp.resolve(this).isNil()) { + if (!assign(cmp, value(true))) { + return false; + } + } + else { + if (!assign(cmp, value(false))) { + return false; + } + } + } + else { + if (!assign(cmp, value(false))) { + return false; + } + } + break; + } + case IFFF: + { + value cmp = n_c->args.args[0].resolve(this); + value gt = n_c->args.args[1].resolve(this); + if (cmp.type == datatypes::boolean || cmp.isNil()) { + if (!cmp.b || cmp.isNil()) { + n_pos = seek(gt.getPrintable(), n_cmds, LABL, n_pos); + } + } + break; + } + case GOTO: + { + value labl = n_c->args.args[0]; + if (isEnabled("forwardlabels")) { + size_t nnpos = seek(labl.resolve(this).getPrintable(), n_cmds, LABL, n_pos); // Seek from next pos (pos++) to end of cmds + if (!nnpos) { + // This could be a method, it could, but it isn't. We jump to searching from the beginning of the block + goto seek_from_1; + } + else { + n_pos = nnpos; + } + break; + } + seek_from_1: + size_t nnpos = seek(labl.resolve(this).getPrintable(), n_cmds, LABL, 0); + if (!nnpos) { + push_error(errors::error{ errors::choice_unknown ,utils::concat("Unknown label '",labl.resolve(this).getPrintable(),"'!") }); + return false; + } + else { + n_pos = nnpos; + } + } + break; + case RETN: + { + value ret = n_c->args.args[0].resolve(this); + //c->args.args[0]->nuke(); // Lets clean this up + return_stack.push(ret); + return true; // We did it, let's return this + } + break; + case OFUN: + { + if (n_c->args.args[0].resolve(this).type == datatypes::custom) { + auto cust = n_c->args.args[0].resolve(this); + auto fname = n_c->args.args[1].getString(); + auto assn = n_c->args.args[2]; + dms_args args; + for (int i = 3; i < n_c->args.args.size(); i++) { + args.push(n_c->args.args[i]); + } + if (inv_map.count(cust.ctype)) { + Invoker* inv = inv_map[cust.ctype]; + auto ret = inv->Invoke(fname, cust.c, this, &args); + if (assn.type != datatypes::nil) { + if (!assign(assn, ret)) { + return false; + } + } + } + else { + error("Custom object not assoiated with any functions!"); + } + } + else { + std::string obj = n_c->args.args[0].getPrintable(); + if (obj == "nil") { + obj = n_c->args.args[0].getPrintable(); + } + std::string funcname = n_c->args.args[1].getPrintable(); + value assn = n_c->args.args[2]; + dms_args args; + + for (int i = 3; i < n_c->args.args.size(); i++) { + args.push(n_c->args.args[i]); + } + + value ret; + if (characterExists(obj)) { + ret = getCharacter(obj)->Invoke(funcname, this, &args); + } + else if (environmentExists(obj)) { + ret = getEnvironment(obj)->Invoke(funcname, this, &args); + } + if (ret.type == datatypes::error) + return false; + if (assn.type != datatypes::nil) { + if (!assign(assn, ret)) { + return false; + } + } + } + } + break; + case FUNC: + { + std::string funcname = n_c->args.args[0].getPrintable(); + value assn = n_c->args.args[1]; + dms_args args; + value ret; + for (int i = 2; i < n_c->args.args.size(); i++) { + args.push(n_c->args.args[i]); + } + // If we have a block made function we don't invoke like normal + if (functionExists(funcname)) { + call_stack.push(funcname); + ret = invoker.Invoke("$BlockInvoke$", this, &args); + } + else { + ret = invoker.Invoke(funcname, this, &args); + } + if (ret.type == datatypes::error) + return false; + if (assn.type != datatypes::nil) { + if (!assign(assn, ret)) { + return false; + } + } + } + break; + case ASID: + { + value env = n_c->args.args[1]; + value indx = n_c->args.args[2].resolve(this); + value assn = n_c->args.args[3].resolve(this); + if (env.type == datatypes::block && blockExists(env.getString())) { // If this is a block let's handle this + enviroment* e = nullptr; + if (environments.count(env.getString())) { + e = environments[env.getString()]; + } + else if (characters.count(env.getString())) { + e = characters[env.getString()]; + } + e->values[indx.getString()] = assn; + } + else if (env.type == datatypes::env) { + if (indx.type == datatypes::number) { + env.e->pushValue(assn); + } + else { + push_error(errors::error{ errors::invalid_type ,concat("Expected a number value got ",datatype[indx.type]) }); + return false; + } + } + else if (env.type == datatypes::custom) { + //env.c->NewIndex(indx, assn); + //if(!assign( assn, env->c->Index(indx)); + // Call the method within the custom data + } + break; + } + case ADD: + { + value assn = n_c->args.args[0]; + value o1 = n_c->args.args[1]; + value o2 = n_c->args.args[2]; + value ret = o1.resolve(this) + o2.resolve(this); + if (!assign(assn, ret)) { + return false; + } + } + break; + case SUB: + { + value assn = n_c->args.args[0]; + value o1 = n_c->args.args[1]; + value o2 = n_c->args.args[2]; + value ret = o1.resolve(this) - o2.resolve(this); + if (!assign(assn, ret)) { + return false; + } + } + break; + case MUL: + { + value assn = n_c->args.args[0]; + value o1 = n_c->args.args[1]; + value o2 = n_c->args.args[2]; + value ret = o1.resolve(this) * o2.resolve(this); + if (!assign(assn, ret)) { + return false; + } + } + break; + case DIV: + { + value assn = n_c->args.args[0]; + value o1 = n_c->args.args[1]; + value o2 = n_c->args.args[2]; + value ret = o1.resolve(this) / o2.resolve(this); + if (!assign(assn, ret)) { + return false; + } + } + break; + case POW: + { + value assn = n_c->args.args[0]; + value o1 = n_c->args.args[1]; + value o2 = n_c->args.args[2]; + value ret = pow(o1.resolve(this).n, o2.resolve(this).n); + if (!assign(assn, ret)) { + return false; + } + } + break; + case MOD: + { + value assn = n_c->args.args[0]; + value o1 = n_c->args.args[1]; + value o2 = n_c->args.args[2]; + value ret = std::fmod(o1.resolve(this).n, o2.resolve(this).n); + if (!assign(assn, ret)) { + return false; + } + } + break; + case INDX: + { + value assn = n_c->args.args[0]; + value env = n_c->args.args[1]; + value indx = n_c->args.args[2].resolve(this); + if (env.type == datatypes::block && blockExists(env.getString())) { // If this is a block let's handle this + enviroment* e = nullptr; + if (environments.count(env.getString())) { + e = environments[env.getString()]; + } + else if (characters.count(env.getString())) { + e = characters[env.getString()]; + } + if (!assign(assn, e->values[indx.getPrintable()])) { + return false; + } + } + else if (env.type == datatypes::env) { + if (indx.type == datatypes::number) { + if (!assign(assn, env.e->getValue(indx))) { + return false; + } + } + else { + push_error(errors::error{ errors::invalid_type ,concat("Expected a number value got ",datatype[indx.type]) }); + return false; + } + } + else if (env.type == datatypes::custom) { + //if(!assign( assn, env.c->Index(indx))) { + // return false; + //} + // Call the method within the custom data + } + } + break; + case LIST: + //We need to create an enviroment value then set that + { + dms_list* env = new dms_list; + // Inject the size of the list + env->hpart["$size"] = n_c->args.args[1]; + value val = new value; + val.set(env); + if (!assign(n_c->args.args[0], val)) { + return false; + } + } + break; + case INST: + { + value list = (*mem)[n_c->args.args[0].getPrintable()]; + list.e->pushValue(n_c->args.args[1]); + } + break; + case COMP: + { + comp cmp = (comp)n_c->args.args[0].i; + value assn = n_c->args.args[1]; + value left = n_c->args.args[2].resolve(this); + value right = n_c->args.args[3].resolve(this); + switch (cmp) { + case comp::eq: { + if (!assign(assn, left == right)) { + return false; + } + break; + } + case comp::gt: { + if (left.isNil() || right.isNil()) { push_error(errors::error{ errors::unknown ,"Attempt to compare a nil value!" }); return false; } + if (!assign(assn, left > right)) { + return false; + } + break; + } + case comp::gteq: { + if (left.isNil() || right.isNil()) { push_error(errors::error{ errors::unknown ,"Attempt to compare a nil value!" }); return false; } + if (!assign(assn, left >= right)) { + return false; + } + break; + } + case comp::lt: { + if (left.isNil() || right.isNil()) { push_error(errors::error{ errors::unknown ,"Attempt to compare a nil value!" }); return false; } + if (!assign(assn, left < right)) { + return false; + } + break; + } + case comp::lteq: { + if (left.isNil() || right.isNil()) { push_error(errors::error{ errors::unknown ,"Attempt to compare a nil value!" }); return false; } + if (!assign(assn, left <= right)) { + return false; + } + break; + } + case comp::nteq: { + if (!assign(assn, left != right)) { + return false; + } + break; + } + } + } + break; + case HALT: + //wait(); + //sleep(700); + std::cout << std::endl; + break; + case WAIT: + sleep((int)(n_c->args.args[0].n * 1000)); + break; + case DSPD: + if (speaker == nullptr) { + push_error(errors::error{ errors::unknown ,utils::concat("A call to set speaker speed, but a speaker has not been defined!") }); + return false; + } + else { + speaker->spd = n_c->args.args[0].n; + } + break; + case SSPK: + //Because we are using void* we must cast our pointers + if (characterExists(n_c->args.args[0].getString())) { + speaker = getCharacter(n_c->args.args[0].getString()); + if (!handler->handleSpeaker(this, speaker)) + return false; + } + else { + push_error(errors::error{ errors::disp_unknown,concat("Unknown character '",n_c->args.args[0].getString(),"'!") }); + return false; + } + break; + case APND: + if (!handler->handleMessageAppend(this, n_c->args.args[0].resolve(this).getPrintable())) + return false; + break; + case CHAR: + { + std::string cha = n_c->args.args[0].getString(); + getCharacter(cha); + break; + } + case DISP: + { + if (!handler->handleMessageDisplay(this, n_c->args.args[0].resolve(this).getPrintable())) + return false; + } + break; + case ASGN: + if (!assign(n_c->args.args[0], n_c->args.args[1])) { + return false; + } + break; + case LINE: + cur_line = (size_t)n_c->args.args[0].i; + break; + case NOOP: + break; + case CHOI: + //Because we are using void* we must cast our pointers + { + std::vector args; + std::string prompt = n_c->args.args[0].getString(); + std::string fn = n_c->args.args[1].getString(); + for (size_t i = 2; i < n_c->args.args.size(); i++) + args.push_back(n_c->args.args[i].resolve(this).getString()); + size_t npos = handler->handleChoice(this, prompt, args); + size_t nnpos = seek(concat("CHOI_", fn, "_", npos), n_cmds, LABL, n_pos); + if (!nnpos) { + push_error(errors::error{ errors::choice_unknown ,utils::concat("Unknown choice!") }); + return false; + } + else { + n_pos = nnpos; + } + } + break; + case JUMP: + // Value assert resolves the data so a variable must eventually equal a string + if (utils::valueassert(n_c->args, this, datatypes::string)) { + std::string block = n_c->args.args[0].resolve(this).getString(); + if (chunks[block] == NULL) { + push_error(errors::error{ errors::non_existing_block ,utils::concat("Attempted to Jump to a non existing block [",block,"]") }); + return false; + } + else if (chunks[block]->type != bt_block) { + push_error(errors::error{ errors::non_existing_block ,utils::concat("Attempted to Jump to a non standard block [",block,"] type: ",getBlockType(chunks[block]->type)) }); + return false; + } + else { + init(chunks[block], n_pos, n_max, n_cmds); + } + } + else { + //utils::print(c->args.args[0].type); + datatypes set = n_c->args.args[0].resolve(this).type; + //utils::print("> ",set); + push_error(errors::error{ errors::invalid_arguments, utils::concat("String expected got ",datatype[set]), true, n_ln }); + return false; + } + break; + default: + break; + } + if (n_pos == n_max) { + // How did we get here? The end of a block? + return false; + } return true; } } \ No newline at end of file diff --git a/DMS/dump.bin b/DMS/dump.bin index d5bd542..6bba8ff 100644 Binary files a/DMS/dump.bin and b/DMS/dump.bin differ diff --git a/DMS/dump.txt b/DMS/dump.txt index fb3c30c..35a38a0 100644 Binary files a/DMS/dump.txt and b/DMS/dump.txt differ diff --git a/DMS/font.ttf b/DMS/font.ttf new file mode 100644 index 0000000..12de5cb Binary files /dev/null and b/DMS/font.ttf differ diff --git a/DMS/font2.ttf b/DMS/font2.ttf new file mode 100644 index 0000000..04facda Binary files /dev/null and b/DMS/font2.ttf differ diff --git a/DMS/gui.h b/DMS/gui.h new file mode 100644 index 0000000..2b7bf5c --- /dev/null +++ b/DMS/gui.h @@ -0,0 +1,142 @@ +#pragma once +#include "window.h" +#include "pch.h" +#include "dms_state.h" +namespace gui { + using namespace std; + using namespace dms; + int __ElementCount = 0; + void init(dms_state* state) { + // While very unlikely it is possible multiple windows to be created! It might be a good idea to support it sometime down the line + window::OnWindowCreated += [](sf::RenderWindow* window) { + + }; + } + /* + textbox + textbutton + textlabel + + frame + + imagelabel + imagebutton + + anim/sprite + video + + + */ + enum class gui_types{frame,text,text,image,sprite,video}; + struct Dim { + float x; + float y; + Dim() {x = 0;y = 0;} + Dim(const Dim &d) { x = d.x; y = d.y;} + Dim(float x, float y) { this->x = x; this->y = y;} + inline void Set(Dim d) {x = d.x; y = d.y;} + inline void Set(float x, float y) { this->x = x; this->y = y;} + }; + struct DualDim { + Dim Position; + Dim Size; + DualDim() {Position.x = 0;Position.y = 0;Size.x = 0;Size.y = 0;} + DualDim(const DualDim& d) { Position = d.Position; Size = d.Size;} + DualDim(Dim pos, Dim size) { Position = pos; Size = size;} + DualDim(float x, float y, float x2, float y2) { Position.x = x; Position.y = y; Size.x = x2; Size.y = y2; } + inline void Set(DualDim d){ Position = d.Position; Size = d.Size;} + inline void Set(Dim pos, Dim size) {Position.x = pos.x;Position.y = pos.y;Size.x = size.x;Size.y = size.y;} + inline void Set(float x, float y, float x2, float y2) { Position.x = x; Position.y = y; Size.x = x2; Size.y = y2;} + }; + struct MouseStats { + float x; + float y; + float dx; + float dy; + char button; + MouseStats(Dim pos, char b) { + x = pos.x; + y = pos.y; + button = b; + } + MouseStats(float xx, float yy, char b) { + x = xx; + y = yy; + button = b; + } + MouseStats(float xx, float yy, float dxx, float dyy) { + x = xx; + y = yy; + dx = dxx; + dy = dyy; + button = 0; + } + }; + struct Keyboard { + // + }; + struct guibase { + //Connections and objects to inheret + multi::connection OnPressed; + multi::connection OnReleased; + multi::connection OnPressedOuter; + multi::connection OnReleasedOuter; + multi::connection OnMousedMoved; + multi::connection WhileHovering; + + multi::connection OnMouseEnter; + multi::connection OnMouseExit; + + + multi::connection OnUpdate; + + }; + class gui : guibase { + + public: + gui_types Type; + DualDim Offset; + DualDim Scale; + DualDim Absolute; + vector Children; + bool Visible = true; + + //map Named; + + gui() {__ElementCount++;} + gui(DualDim offset, DualDim scale) { Offset = offset; Scale = scale;} + gui(float x,float y,float w,float h,float sx,float sy,float sw,float sh){Offset.Position.x = x;Offset.Position.y = y;Offset.Size.x = w;Offset.Size.y = h;Scale.Position.x = sx;Scale.Position.y = sy;Scale.Size.x = sw;Scale.Size.y = sh;} + void SetDualDim(DualDim offset,DualDim scale) {Offset = offset;Scale = scale;} + + virtual void Draw() { + return; // Override this. + } + + inline vector& GetChildren() {return Children;} + inline void GetAllChildren(vector& ref) { + auto temp = GetChildren(); + for (int i = 0; i < temp.size(); i++) { + ref.push_back(&temp[i]); + temp[i].GetAllChildren(ref); + } + } + inline vector GetAllChildren() { + auto temp = GetChildren(); + vector everything; + everything.reserve(__ElementCount); // Reserve all the current elements that exist + for (int i = 0; i < temp.size(); i++) { + everything.push_back(&temp[i]); + temp[i].GetAllChildren(everything); + } + return everything; + } + }; + // Draw Everything + gui _Root; + void Draw() { + auto childs = _Root.GetAllChildren(); + for (int i = 0; i < childs.size(); i++) { + childs[i]->Draw(); + } + } +} \ No newline at end of file diff --git a/DMS/pch.h b/DMS/pch.h index fa1d0cb..c32c97d 100644 --- a/DMS/pch.h +++ b/DMS/pch.h @@ -1,4 +1,5 @@ #pragma once +#include #include #include #include diff --git a/DMS/sound.h b/DMS/sound.h index ab9c75f..907b16a 100644 --- a/DMS/sound.h +++ b/DMS/sound.h @@ -1,5 +1,4 @@ #pragma once -#include "pch.h" #include #include "dms_state.h" namespace dms::audio { diff --git a/DMS/test.dms b/DMS/test.dms index 2dc83d4..6f16f08 100644 --- a/DMS/test.dms +++ b/DMS/test.dms @@ -17,17 +17,11 @@ music2 = loadMusic("test.ogg") [main] // Let's extend the base feature set - - - music.setPitch(.7) - print(music.getStatus()) music.play() - print(music.getStatus()) - print("Type: " + type(music2)) - while(music.getStatus()!="stopped"){ - wait 1 - } - print("Done") + music.setVolume(5) + while(music.getStatus()!="stopped"){} + print("Sound finished!") + // a = 0 // while (true){ // asm { @@ -53,7 +47,7 @@ music2 = loadMusic("test.ogg") } } -[player:function(song)] +[player:function(song,food)] choice "What you wanna do?" { "play/resume" { song.play() diff --git a/DMS/window.cpp b/DMS/window.cpp new file mode 100644 index 0000000..9e403c0 --- /dev/null +++ b/DMS/window.cpp @@ -0,0 +1,22 @@ +#include "pch.h" +#include "window.h" +namespace dms::window { + Invoker* inv = new Invoker; + void init(dms_state* state) { + /* + inv->registerFunction("getStatus", getStatus); + + state->assoiateType("audiostream",inv); + state->invoker.registerFunction("loadMusic", loadMusic); + */ + } + value newWindow(void* self, dms_state* state, dms_args* args) { + if (dms::utils::valueassert(*args, state, datatypes::number, datatypes::number, datatypes::number)) { + + } + else if (dms::utils::valueassert(*args, state, datatypes::int64, datatypes::int64, datatypes::int64)) { + + } + sf::RenderWindow window(sf::VideoMode(1024, 768, 32), "Background Test"); + } +} \ No newline at end of file diff --git a/DMS/window.h b/DMS/window.h new file mode 100644 index 0000000..d695a85 --- /dev/null +++ b/DMS/window.h @@ -0,0 +1,14 @@ +#pragma once +#include +#include +#include "dms_state.h" +#include "utils.h" +#include +#include "Connection.h" +namespace dms::window { + multi::connection OnWindowCreated; + void init(dms_state*); + bool windowIsReady = false; + std::vector windows; + value newWindow(void*, dms_state*, dms_args*); +} \ No newline at end of file diff --git a/background.jpg b/background.jpg new file mode 100644 index 0000000..b0f8b80 Binary files /dev/null and b/background.jpg differ diff --git a/test.ogg b/test.ogg new file mode 100644 index 0000000..430d946 Binary files /dev/null and b/test.ogg differ diff --git a/test2.ogg b/test2.ogg new file mode 100644 index 0000000..bddd6f1 Binary files /dev/null and b/test2.ogg differ