Untitled

 avatar
unknown
plain_text
9 months ago
13 kB
17
Indexable
#include <iostream>
#include "Story.h"
#include <string>
#include "ButtonProperties.h"
#include <nlohmann/json.hpp>
#include <filesystem>
#include <SDL3/SDL.h>
#include <vector>
#include "StoryCard.h"
#include <fstream>
#include <sstream>
#include <sol/sol.hpp>
#include "engine/Dialogue.h"
#include "engine/Event.h"
#include "engine/Actor.h"
#include "engine/data_types/IscVec2.h"
#include "engine/Background.h"
#include <miniaudio.h>
#include "engine/data_types/IscAudio.h"
#include "engine/data_types/IscAnimation.h"
#include "engine/Audio.h"
#include "engine/Win.h"
#include "engine/Var.h"
#include <variant>
#include "engine/data_types/IscActor.h"

#define SOL_SAFE_NUMERICS 1

using json = nlohmann::json;

Story::Story(SDL_Renderer* renderer, SDL_Window* window) {
    m_window = window;

    m_renderer = renderer;

    m_lua.open_libraries(sol::lib::base, sol::lib::package);

    MakeFuncAvailableToLua();
}

void Story::SetData(std::string filename, json data) {
    m_filename = filename;

    ButtonProperties buttonProperties;
    buttonProperties.text = data["story_main_menu"]["button"]["text"].get<std::string>();
    buttonProperties.rect = SDL_FRect{0.0f, 0.0f, 100.0f, 40.0f};
    buttonProperties.roundBorder = data["story_main_menu"]["button"]["round_border"].get<bool>();
    buttonProperties.color = SDL_Color{
        static_cast<uint8_t>(data["story_main_menu"]["button"]["color"][0].get<int>()),
        static_cast<uint8_t>(data["story_main_menu"]["button"]["color"][1].get<int>()),
        static_cast<uint8_t>(data["story_main_menu"]["button"]["color"][2].get<int>()),
        static_cast<uint8_t>(data["story_main_menu"]["button"]["color"][3].get<int>())
    };

    std::filesystem::path backgroundPath = "C:/ISCreator/Stories"/std::filesystem::path(filename)/data["story_main_menu"]["background"].get<std::string>();

    m_storyMainMenu = StoryMainMenu(buttonProperties, data["card_info"]["story_name"].get<std::string>(), backgroundPath.string(), m_renderer);
    m_storyMainMenu.initialized = true;
}

void Story::Event(SDL_Event& event) {
    if (event.type == SDL_EVENT_USER) {
        if (event.user.code == 0) {
            if (m_dialogueHandler.dialogue.length() > 403) m_dialogueHandler.dialogue.erase(0, 1);
            m_dialogueHandler.dialogue += m_dialogueHandler.tempDialogue[m_dialogueHandler.count];
            m_dialogueHandler.count += 1;

        } else if (event.user.code == 1) {
            for (auto it = m_events.begin(); it != m_events.end(); it++) {
                if (it->eventID == *static_cast<int*>(event.user.data1)) {
                    std::string eventName = it->eventName;
                    int eventID = it->eventID;
                    m_events.erase(it);

                    if (m_eventFunctions.size() > 0) {
                        for (auto func:m_eventFunctions) {
                            func(eventName, eventID);
                        }
                    }
                    break;
                }
            }
        } else if (event.user.code == 2) {
            if (static_cast<IscAnimData*>(event.user.data1)->count != static_cast<IscAnimData*>(event.user.data1)->frames.size()-1) {
                static_cast<IscAnimData*>(event.user.data1)->count += 1;

            } else if (static_cast<IscAnimData*>(event.user.data1)->count == static_cast<IscAnimData*>(event.user.data1)->frames.size()-1) {
                if (static_cast<IscAnimData*>(event.user.data1)->looped) {
                    static_cast<IscAnimData*>(event.user.data1)->count = 0;

                } else {
                    SDL_RemoveTimer(static_cast<IscAnimData*>(event.user.data1)->animationTimer);
                    static_cast<IscAnimData*>(event.user.data1)->isPlaying = false;
                    static_cast<IscAnimData*>(event.user.data1)->onComplete();
                }
            }
        }
    } else if (event.type == SDL_EVENT_WINDOW_RESIZED) {
        AddEvent("WINDOW_RESIZED", 0);

    } else if (event.type == SDL_EVENT_KEY_DOWN) {
        if (event.key.scancode != SDL_SCANCODE_ESCAPE) {
            AddEvent(SDL_GetKeyName(event.key.key), 0);
        }
    }
}

void Story::RunScripts() {
    std::filesystem::path scriptsPath = std::filesystem::path("C:/ISCreator/Stories/")/m_filename/"scripts";

    for (auto script:std::filesystem::directory_iterator(scriptsPath)) {
        if (script.path().extension() == ".lua") {
            std::ifstream stream(script.path());
            m_lua.script_file(script.path().string());

            sol::object func = m_lua["event"];
            
            if (func.is<sol::function>()) {
                m_eventFunctions.emplace_back(func);
            }
        }
    }
}

void Story::MakeFuncAvailableToLua() {
    //Engine data types
    sol::usertype<IscVec2> iscVec2Type = m_lua.new_usertype<IscVec2>("IscVec2", sol::constructors<IscVec2(float x_, float y_)>());
    iscVec2Type["x"] = &IscVec2::x;
    iscVec2Type["y"] = &IscVec2::y;

    sol::usertype<IscActor> iscActorType = m_lua.new_usertype<IscActor>("IscActor", sol::constructors<IscActor()>());
    iscActorType["name"] = &IscActor::name;
    iscActorType["actorID"] = sol::readonly(&IscActor::actorID);
    iscActorType["size"] = &IscActor::size;
    iscActorType["position"] = &IscActor::position;
    iscActorType["add_animation"] = &IscActor::AddAnimation;
    iscActorType["load_animation"] = &IscActor::LoadAnimation;
    iscActorType["unload_animation"] = &IscActor::UnloadAnimation;
    iscActorType["current_animation"] = &IscActor::CurrentAnimation;
    iscActorType["remove_animation"] = &IscActor::RemoveAnimation;
    iscActorType["get_animations"] = &IscActor::GetAnimations;

    sol::usertype<IscAudio> iscAudioType = m_lua.new_usertype<IscAudio>("IscAudio", sol::constructors<IscAudio()>());
    iscAudioType["audioName"] = &IscAudio::audioName;
    iscAudioType["audioID"] = sol::readonly(&IscAudio::audioID);
    iscAudioType["play"] = &IscAudio::Play;
    iscAudioType["stop"] = &IscAudio::Stop;
    iscAudioType["play_from_beginning"] = &IscAudio::PlayFromBeginning;
    iscAudioType["seek"] = &IscAudio::Seek;

    sol::usertype<IscVar> iscVarType = m_lua.new_usertype<IscVar>("IscVar", sol::constructors<IscVar()>());
    iscVarType["name"] = sol::readonly(&IscVar::name);
    iscVarType["type"] = sol::readonly(&IscVar::type);
    iscVarType["value"] = sol::readonly(&IscVar::value);
    iscVarType["isConstant"] = sol::readonly(&IscVar::isConstant);
    iscVarType["set_value"] = sol::overload(
        [](IscVar& self, int value_) {self.SetValue(value_);},
        [](IscVar& self, float value_) {self.SetValue(value_);},
        [](IscVar& self, std::string value_) {self.SetValue(value_);},
        [](IscVar& self, bool value_) {self.SetValue(value_);},
        [](IscVar& self, sol::table value_) {self.SetValue(value_);}
    );

    sol::usertype<IscAnimation> iscAnimationType = m_lua.new_usertype<IscAnimation>("IscAnimation", sol::constructors<IscAnimation(
        std::string name,
        sol::table frames,
        std::string spritesheet,
        IscAnimData animData
    )>());

    iscAnimationType["name"] = &IscAnimation::name;
    iscAnimationType["animationID"] = sol::readonly(&IscAnimation::animationID);
    iscAnimationType["play"] = &IscAnimation::Play;

    sol::usertype<IscAnimData> iscAnimDataType = m_lua.new_usertype<IscAnimData>("IscAnimData", sol::constructors<IscAnimData(float duration_, bool looped_, sol::function onComplete)>());
    iscAnimDataType["duration"] = &IscAnimData::duration;
    iscAnimDataType["looped"] = &IscAnimData::looped;
    iscAnimDataType["onComplete"] = &IscAnimData::onComplete;

    //Dialogue functions
    m_lua.set_function("start_dialogue", StartDialogue);
    m_lua.set_function("show_dialogue_box", ShowDialogueBox);
    m_lua.set_function("instant_dialogue", InstantDialogue);
    m_lua.set_function("clear_dialogue", ClearDialogue);

    //Event functions
    m_lua.set_function("add_event", AddEvent);
    m_lua.set_function("remove_events_with_name", RemoveEventsWithName);
    m_lua.set_function("remove_event", RemoveEvent);
    m_lua.set_function("clear_events", ClearEvents);
    m_lua.set_function("get_events", GetEvents);

    //Actor functions
    m_lua.set_function("add_actor", AddActor);
    m_lua.set_function("get_actor_by_id", [](int actorID) {
        return GetActorByID(actorID);
    });
    m_lua.set_function("remove_actors_with_name", RemoveActorsWithName);
    m_lua.set_function("remove_actor", RemoveActor);

    //Background functions
    m_lua.set_function("set_background", SetBackground);
    m_lua.set_function("clear_background", ClearBackground);

    //Audio functions
    m_lua.set_function("add_audio", AddAudio);
    m_lua.set_function("get_audio_by_id", [](int audioID) {
        return GetAudioByID(audioID);
    });
    m_lua.set_function("remove_audio", RemoveAudio);
    m_lua.set_function("remove_audio_with_name", RemoveAudioWithName);

    //Window functions
    m_lua.set_function("get_window_size", GetWindowSize);

    //Var functions
    m_lua.set_function("create_variable", sol::overload(
        [](std::string name, std::string type, int value, bool isConstant) {
            return CreateVariable(name, type, value, isConstant);
        },
        [](std::string name, std::string type, float value, bool isConstant) {
            return CreateVariable(name, type, value, isConstant);
        },
        [](std::string name, std::string type, std::string value, bool isConstant) {
            return CreateVariable(name, type, value, isConstant);
        },
        [](std::string name, std::string type, bool value, bool isConstant) {
            return CreateVariable(name, type, value, isConstant);
        },
        [](std::string name, std::string type, sol::table value, bool isConstant) {
            return CreateVariable(name, type, value, isConstant);
        }
    ));

    m_lua.set_function("get_variable", [](std::string name) {
        return GetVariable(name);
    });

    m_lua.set_function("remove_variable", RemoveVariable);
}

void Story::Draw(SDL_Window* window, SDL_Color& screenColor) {
    if (m_storyMainMenu.initialized) m_storyMainMenu.Draw(m_renderer, window, screenColor);

    if (!m_storyMainMenu.initialized) {
       if (m_background != NULL) {
            int winX, winY;

            SDL_GetWindowSize(window, &winX, &winY);

            SDL_FRect backgroundRect = SDL_FRect{
                0.0f,
                0.0f,
                static_cast<float>(winX),
                static_cast<float>(winY)
            };

            SDL_RenderTexture(m_renderer, m_background, NULL, &backgroundRect);
       }

        for (auto a = m_actors.begin(); a != m_actors.end(); a++) {
            a->Draw(m_renderer);
        }
    }

    if (!m_storyMainMenu.initialized && m_storyProperties["showDialogueBox"].get<bool>()) {
        int winX, winY;

        SDL_GetWindowSize(window, &winX, &winY);

        m_dialogueBoxRect.x = (static_cast<float>(winX)-m_dialogueBoxRect.w)/2;
        m_dialogueBoxRect.y = static_cast<float>(winY)-m_dialogueBoxRect.h-20;

        SDL_SetRenderDrawColor(m_renderer, 100, 100, 100, 255);
        SDL_RenderFillRect(m_renderer, &m_dialogueBoxRect);
        SDL_RenderRect(m_renderer, &m_dialogueBoxRect);
    }

    if (m_dialogueHandler.dialogue != "") {
        ImGui::SetCursorPos(ImVec2(m_dialogueBoxRect.x+5, m_dialogueBoxRect.y));
        ImGui::PushFontSize(25.0f);
        ImGui::PushTextWrapPos(ImGui::GetContentRegionAvail().x);
        ImGui::Text(m_dialogueHandler.dialogue.c_str());
        ImGui::PopFontSize();
    }

    if (m_storyMainMenu.runScripts) {
        RunScripts();
        m_storyMainMenu.runScripts = false;
    }
}

void Story::Destroy() {
    m_filename = "";

    if (m_storyMainMenu.initialized) m_storyMainMenu.Destroy();

    if(!m_storyMainMenu.initialized) {
        for (auto eTimer:m_dialogueHandler.eventTimers) {SDL_RemoveTimer(eTimer);}
        m_dialogueHandler.eventTimers.clear();

        for (auto e:m_events) {SDL_RemoveTimer(e.timer);}
        m_events.clear();

        for (auto a:m_actors) {
            SDL_DestroyTexture(a.image);
            if (std::get<1>(a.currentAnimation) != NULL) SDL_DestroyTexture(std::get<1>(a.currentAnimation));
        }
        m_actors.clear();

        if (m_background != NULL) {SDL_DestroyTexture(m_background);}

        for (auto a:m_audio) {ma_sound_uninit(&a.audio);}
        m_audio.clear();

        m_eventFunctions.clear();
    }
}
Editor is loading...
Leave a Comment