public static FrameData Get_Mouth_Frame_Data(OfficialSetData set_data, BustupData bustup_data, MakerCommandData command_data)
        {
            // Create variables for the folder and JSON that contains the data for the set.
            string data_folder = $@"{AssetDirectoryConfig.assetDirectory.assetFolderPath}//SceneMaker//Data//Template_Data//{set_data.Origin}//Bustup//{set_data.ID}";
            string data_sheet  = "mouth_frame_data.json";

            // If the file folder doesn't exist, create it.
            if (!Directory.Exists(data_folder))
            {
                Directory.CreateDirectory(data_folder);
            }

            // If the file exists at the specified directory, load its contents.
            if (File.Exists(data_folder + "/" + data_sheet))
            {
                // Load the data sheet for the selected sprite set.
                frame_data_list = Load_Frame_Data_List(data_folder + "/" + data_sheet).ToList();

                // To create the filename for the frame, delete the file extention at the end of the base bustup's filename first.
                string bustup_filename = bustup_data.Filename.Substring(0, bustup_data.Filename.Length - 4);

                // Combine the base bustup filename substring with the needed frame suffix to create the frame filename.
                string frame_filename = $"{bustup_filename}_m{command_data.Mouth_Frame}.png";

                // Return the frame data info by using its filename to search for its entry.
                return(Frame_Data_From_Filename(frame_filename));
            }
            // If the file doesn't exist, create it.
            else
            {
                Create_Mouth_Frame_Data_List(set_data);
                return(Get_Mouth_Frame_Data(set_data, bustup_data, command_data));
            }
        }
        public static List <BustupData> Create_Bustup_Data_List(OfficialSetData set_data) // For dev purposes only
        {
            var new_list = new List <BustupData>();

            string bustup_path = $@"{AssetDirectoryConfig.assetDirectory.assetFolderPath}//SceneMaker//Templates//{set_data.Origin}//Bustup//{set_data.ID}";
            string data_path   = $@"{AssetDirectoryConfig.assetDirectory.assetFolderPath}//SceneMaker//Data//Template_Data//{set_data.Origin}//Bustup//{set_data.ID}//bustup_data.json";

            // Get a count of how many files are in the sprite set's directory.
            int filecount = OfficialSetMethods.AttachmentCountItemDirectory(bustup_path);

            // Create a loop starting at 1 meant to iterate though every file in the directory.
            // Expression numbers always start at 1, so we'll begin there.
            for (int expression = 1; expression <= filecount; expression++)
            {
                // Inside, create a secondary loop also meant to iterate though every file in the directory.
                // This loop is searching for outfits, which start at 1.
                for (int outfit = 1; outfit <= filecount; outfit++)
                {
                    // Here, we're going to create a file path that could potentially exist given the combination of expression and outfit numbers.
                    // Check if the created file path string exists.
                    if (File.Exists($"{bustup_path}//{set_data.ID.ToLower()}_{expression}_{outfit}.png"))
                    {
                        var new_bustup_data = new BustupData()
                        {
                            Filename             = $"{set_data.ID.ToLower()}_{expression}_{outfit}.png",
                            Default_Name_EN      = "Rise",
                            Default_Name_JPN     = "久慈川 りせ",
                            P4D_Scale_Width      = 1024,
                            P4D_Scale_Height     = 1024,
                            P4D_Left_Coord_X     = -64,
                            P4D_Left_Coord_Y     = 64,
                            P4D_Center_Coord_X   = 448,
                            P4D_Center_Coord_Y   = 64,
                            P4D_Right_Coord_X    = 960,
                            P4D_Right_Coord_Y    = 64,
                            P4D_Nav_Scale_Width  = 0,
                            P4D_Nav_Scale_Height = 0,
                            P4D_Nav_Coord_X      = 0,
                            P4D_Nav_Coord_Y      = 0,
                            P4D_Dual_Flip        = false
                        };
                        new_list.Add(new_bustup_data);
                    }
                }
            }

            try
            {
                string json = JsonConvert.SerializeObject(new_list, Formatting.Indented);
                File.WriteAllText(data_path, json);
            }
            catch (Exception e)
            {
                Console.WriteLine($"'{e}'");
            }

            return(new_list);
        }
        public static BustupData Get_Bustup_Data(UserInfoFields account, OfficialSetData set_data, MakerCommandData command_data)
        {
            // Create variables for the folder and JSON that contains the data for the set.
            string data_folder = $@"{AssetDirectoryConfig.assetDirectory.assetFolderPath}//SceneMaker//Data//Template_Data//{set_data.Origin}//Bustup//{set_data.ID}";
            string data_sheet  = "bustup_data.json";

            // If the file folder doesn't exist, create it.
            if (!Directory.Exists(data_folder))
            {
                Directory.CreateDirectory(data_folder);
            }

            // If the file exists at the specified directory, load its contents.
            if (File.Exists(data_folder + "/" + data_sheet))
            {
                // Load the data sheet for the selected sprite set.
                bustup_data_list = Load_Bustup_Data_List(data_folder + "/" + data_sheet).ToList();

                // START

                /* Console.WriteLine("Copying data...");
                 *
                 * string data_path = $@"{AssetDirectoryConfig.assetDirectory.assetFolderPath}//SceneMaker//Data//Template_Data//{set_data.Origin}//Bustup//{set_data.ID}//bustup_data.json";
                 *
                 * foreach (BustupData s in bustup_data_list)
                 * {
                 *  s.P5S_Coord_X = s.P5R_Coord_X;
                 *  s.P5S_Coord_Y = s.P5R_Coord_Y;
                 *  s.P5S_Scale_Width = s.P5R_Scale_Width;
                 *  s.P5S_Scale_Height = s.P5R_Scale_Height;
                 * }
                 *
                 * try
                 * {
                 *  string json = JsonConvert.SerializeObject(bustup_data_list, Formatting.Indented);
                 *  File.WriteAllText(data_path, json);
                 * }
                 * catch (Exception e)
                 * {
                 *  Console.WriteLine($"'{e}'");
                 * }
                 *
                 * Console.WriteLine("Copy complete!"); */
                // END

                // Find the filename of the bustup that the user has selected.
                string bustup_filename = Get_Bustup_Filename(account, set_data, command_data);

                // Return the bustup data info by using its filename to search for its entry.
                return(Bustup_Data_From_Filename(bustup_filename));
            }
            else
            {
                Create_Bustup_Data_List(set_data);
                return(Get_Bustup_Data(account, set_data, command_data));
            }
        }
        public static string Get_Bustup_Filename(UserInfoFields account, OfficialSetData set_data, MakerCommandData command_data)
        {
            // Establish the directory of the specified sprite set.
            string set_path = $@"{AssetDirectoryConfig.assetDirectory.assetFolderPath}//SceneMaker//Templates//{set_data.Origin}//Bustup//{set_data.ID}";

            // Get a count of how many files are in the sprite set's directory.
            int filecount = OfficialSetMethods.AttachmentCountItemDirectory(set_path);

            // Create a variable for the base sprite's filename. We'll go searching for it in a few moments.
            string base_sprite_filename = "";

            // Create variables that keep track of how many frames of each frame type are present for the base sprite.
            // This will help us perform the math needed to form the sprite sheet.
            //int eye_frame_count = 0;
            //int mouth_frame_count = 0;

            // Check if the sprite set's directory exists.
            if (Directory.Exists(set_path))
            {
                // If so, it's time to find the filename for the user's selected sprite so we can retrieve the frames associated with it.
                // We can do this by creating a counter starting from zero that will increment by one until it reaches the sprite numer the user specified.
                // Once it reaches that number, the iterated filename will be saved and we can use that to find its associated frames.
                int counter            = 0;
                int base_sprite_number = command_data.Base_Sprite;

                // The manner of iteration will change based on the user's settings.
                // First, Order by Outfit.
                if (account.Setting_Sheet_Order == "Order by Outfit")
                {
                    // Create a loop starting at 1 meant to iterate though every file in the directory.
                    // Outfit numbers always start at 1, so we'll begin there.
                    for (int outfit = 1; outfit <= filecount; outfit++)
                    {
                        // Inside, create a secondary loop also meant to iterate though every file in the directory.
                        // This loop is searching for expressions, which start at 1.
                        for (int expression = 1; expression <= filecount; expression++)
                        {
                            // Here, we're going to create a file path that could potentially exist given the combination of expression and outfit numbers.
                            // Check if the created file path string exists.
                            if (File.Exists($"{set_path}//{set_data.ID.ToLower()}_{expression}_{outfit}.png"))
                            {
                                // If the file does exist, increment the counter by one.
                                counter++;

                                // Check if the counter matches the same number of the chosen sprite number.
                                if (counter == base_sprite_number)
                                {
                                    // If it does, we found our sprite! Save the filename to the variable created earlier so we can reference it later.
                                    base_sprite_filename = $"{set_data.ID.ToLower()}_{expression}_{outfit}";

                                    // Break out of the current loop.
                                    break;
                                }
                            }
                        }

                        // Check if the filename variable for the base sprite is not empty.
                        if (base_sprite_filename != "")
                        {
                            // If so, we already found our filename! Break out of the outer loop.
                            break;
                        }
                    }
                }
                // Second case, Order by Expression.
                else if (account.Setting_Sheet_Order == "Order by Expression")
                {
                    // Create a loop starting at 1 meant to iterate though every file in the directory.
                    // Expression numbers always start at 1, so we'll begin there.
                    for (int expression = 1; expression <= filecount; expression++)
                    {
                        // Inside, create a secondary loop also meant to iterate though every file in the directory.
                        // This loop is searching for outfits, which start at 1.
                        for (int outfit = 1; outfit <= filecount; outfit++)
                        {
                            // Here, we're going to create a file path that could potentially exist given the combination of expression and outfit numbers.
                            // Check if the created file path string exists.
                            if (File.Exists($"{set_path}//{set_data.ID.ToLower()}_{expression}_{outfit}.png"))
                            {
                                // If the file does exist, increment the counter by one.
                                counter++;

                                // Check if the counter matches the same number of the chosen sprite number.
                                if (counter == base_sprite_number)
                                {
                                    // If it does, we found our sprite! Save the filename to the variable created earlier so we can reference it later.
                                    base_sprite_filename = $"{set_data.ID.ToLower()}_{expression}_{outfit}";

                                    // Break out of the current loop.
                                    break;
                                }
                            }
                        }

                        // Check if the filename variable for the base sprite is not empty.
                        if (base_sprite_filename != "")
                        {
                            // If so, we already found our filename! Break out of the outer loop.
                            break;
                        }
                    }
                }
            }

            return($"{base_sprite_filename}.png");
        }
        public static List <FrameData> Create_Mouth_Frame_Data_List(OfficialSetData set_data) // For dev purposes only
        {
            // Create a new empty frame data list.
            // This is what we'll be using to create frame data for each image.
            var new_list = new List <FrameData>();

            // Establish the paths for the directory where the eye frames are held, as well as the directory for where the data sheet is held.
            string frame_path = $@"{AssetDirectoryConfig.assetDirectory.assetFolderPath}//SceneMaker//Templates//{set_data.Origin}//Bustup//{set_data.ID}//Mouth";
            string data_path  = $@"{AssetDirectoryConfig.assetDirectory.assetFolderPath}//SceneMaker//Data//Template_Data//{set_data.Origin}//Bustup//{set_data.ID}//mouth_frame_data.json";

            // Initialize a new int variable to zero.
            // We'll need this to store how many frames are in the eye frame directory.
            int filecount = 0;

            // Check if the eye frame directory established exists.
            // If so, change the filecount int to how many images are in the eye frame directory.
            if (Directory.Exists(frame_path))
            {
                filecount = OfficialSetMethods.AttachmentCountItemDirectory(frame_path);
            }
            // If not, return null.
            else
            {
                return(null);
            }

            // Create a loop starting at 1 meant to iterate though every file in the directory.
            // Expression numbers always start at 1, so we'll begin there.
            for (int expression = 1; expression <= filecount; expression++)
            {
                // Inside, create a secondary loop also meant to iterate though every file in the directory.
                // This loop is searching for outfits, which start at 1.
                for (int outfit = 1; outfit <= filecount; outfit++)
                {
                    // Get the current filename generated from the for loops.
                    // This name isn't guaranteed to exist, but we will test it soon to find out.
                    string current_filename = $"{set_data.ID.ToLower()}_{expression}_{outfit}";

                    // Let's get the file count for any images in the directory that share the same base sprite filename substring as our current generated name.
                    // We do that by forming an array of all filenames that match.
                    string[] allFiles = Directory.GetFiles(frame_path, $"{current_filename}_m*.png");

                    // Take the length of the array and assign it to a new int variable.
                    int base_sprite_eye_frame_count = allFiles.Length;

                    // We're already within two loops to generate the base filename, but now we need to use another loop to iterate through potentially multiple frames for the same sprite.
                    for (int i = 1; i <= base_sprite_eye_frame_count; i++)
                    {
                        // Here, we're going to create a file path that could potentially exist given the combination of expression and outfit numbers.
                        // Check if the created file path string exists.
                        if (File.Exists($"{frame_path}//{set_data.ID.ToLower()}_{expression}_{outfit}_m{i}.png"))
                        {
                            // If so, generate a new frame data object for the frame.
                            var new_frame_data = new FrameData()
                            {
                                Filename     = $"{set_data.ID.ToLower()}_{expression}_{outfit}_m{i}.png",
                                Scale_Width  = 176,
                                Scale_Height = 100,
                                Coord_X      = 268,
                                Coord_Y      = 537
                            };
                            new_list.Add(new_frame_data);
                        }
                    }
                }
            }

            // Write all text to the data file.
            try
            {
                string json = JsonConvert.SerializeObject(new_list, Formatting.Indented);
                File.WriteAllText(data_path, json);
            }
            catch (Exception e)
            {
                Console.WriteLine($"'{e}'");
            }

            return(new_list);
        }
Example #6
0
        public static async Task Render_Quick_Scene_P4D(SocialLinkerCommand sl_command, OfficialSetData set_data, MakerCommandData command_data)
        {
            // Create variables to store the width and height of the template.
            int template_width  = 1920;
            int template_height = 1080;

            // Create two variables for the command user and the command channel, derived from the message object taken in.
            SocketUser        user    = sl_command.User;
            SocketTextChannel channel = (SocketTextChannel)sl_command.Channel;

            // Send a loading message to the channel while the sprite sheet is being made.
            RestUserMessage loader = await channel.SendMessageAsync("", false, P4D_Loading_Message().Build());

            // Get the account information of the command's user.
            var account = UserInfoClasses.GetAccount(user);

            BustupData bustup_data = BustupDataMethods.Get_Bustup_Data(account, set_data, command_data);

            // Create a starting base bitmap to render all graphics on.
            Bitmap base_template = new Bitmap(template_width, template_height);

            // Create another bitmap the same size.
            // In case the user has set a colored bitmap in their settings, we'll need to use this to render it.
            Bitmap colored_background_bitmap = new Bitmap(template_width, template_height);

            // Here, we want to grab any images attached to the message to use it as a background.
            // Create a variable for the message attachment.
            var attachments = sl_command.Attachments;

            // Create an empty string variable to hold the URL of the attachment.
            string url = "";

            // If there are no attachments on the message, set the URL string to "None".
            if (attachments == default || attachments.LongCount() == 0)
            {
                url = "None";
            }
            // Else, assign the URL of the attachment to the URL string.
            else
            {
                url = attachments.ElementAt(0).Url;
            }

            // Initialize a bitmap object for the user's background. It's small now because we'll reassign it depending on our circumstances.
            Bitmap background = new Bitmap(2, 2);

            // If a URL for a message attachment exists, download it and copy its contents to the bitmap variable we just created.
            if (url != "None")
            {
                // Here, we'll want to try and retrieve the user's input image.
                try
                {
                    // Declare variables for a web request to retrieve the image.
                    System.Net.HttpWebRequest webRequest = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(url);
                    webRequest.AllowWriteStreamBuffering = true;
                    webRequest.Timeout = 30000;

                    // Create a stream and download the image to it.
                    System.Net.WebResponse webResponse = webRequest.GetResponse();
                    System.IO.Stream       stream      = webResponse.GetResponseStream();

                    // Copy the stream's contents to the background bitmap variable.
                    background = (Bitmap)System.Drawing.Image.FromStream(stream);

                    webResponse.Close();
                }
                // If an exception occurs here, the filetype is likely incompatible.
                // Send an error message, delete the loading message, and return.
                catch (System.ArgumentException e)
                {
                    Console.WriteLine(e);
                    await loader.DeleteAsync();

                    _ = ErrorHandling.Incompatible_File_Type(sl_command);
                    return;
                }
            }

            // Render the uploaded image based on the user's background settings.
            switch (account.Setting_BG_Upload)
            {
            case "Maintain Aspect Ratio":
                background = Center_Image(background);
                break;

            case "Stretch to Fit":
                background = Stretch_To_Fit(background);
                break;
            }

            // The user may have a custom mono-colored background designated in their settings. Let's handle that now.
            // Check if the user's background color setting is set to something other than "Transparent".
            // If so, we have a color to render for the background!
            if (account.Setting_BG_Color != "Transparent")
            {
                // Convert the user's HTML color setting to one we can use and assign it to a color variable.
                System.Drawing.Color user_background_color = System.Drawing.ColorTranslator.FromHtml(account.Setting_BG_Color);

                // Color the entirety of the background bitmap the user's selected color.
                using (Graphics graphics = Graphics.FromImage(colored_background_bitmap))
                {
                    graphics.Clear(user_background_color);
                }
            }

            // Next, time for the conversation portrait! Create and initialize a new bitmap variable for it.
            Bitmap bustup = new Bitmap(2, 2);

            // Check if the base sprite number is something other than zero.
            // If it is zero, we have nothing to render. Otherwise, retrieve the bustup.
            if (command_data.Base_Sprite != 0)
            {
                bustup = OfficialSetMethods.Bustup_Selection(sl_command, account, set_data, bustup_data, command_data);
            }

            // If the bustup returns as null, however, something went wrong with rendering the animation frames.
            // An error message has already been sent in the frame rendering method, so delete the loading message and return.
            if (bustup == null)
            {
                await loader.DeleteAsync();

                return;
            }

            // Time to put it all together!
            using (Graphics graphics = Graphics.FromImage(base_template))
            {
                // Draw the layer with the user's colored default background if it exists.
                graphics.DrawImage(colored_background_bitmap, 0, 0, template_width, template_height);

                // Draw the user's background to the base template.
                graphics.DrawImage(background, 0, 0, template_width, template_height);

                // Draw the character bust-up to the template if the base sprite number is not '0'.
                if (command_data.Base_Sprite != 0)
                {
                    graphics.DrawImage(bustup, bustup_data.P4D_Center_Coord_X, bustup_data.P4D_Center_Coord_Y, bustup_data.P4D_Scale_Width, bustup_data.P4D_Scale_Height);
                }

                // Now, it's time to render the text.
                // Render the character's name to the template.
                // Check if the base sprite number is something other than zero.
                if (command_data.Base_Sprite != 0)
                {
                    //graphics.DrawImage(Text_To_Blue(Render_Name(bustup_data)), 0, 0, template_width, template_height);
                }
                // If the base sprite number IS zero, we need a sprite to actually retrieve a display name from.
                else
                {
                    // Change the base sprite number from the command data to one.
                    // This way, we can get the bustup data for the first sprite to retrieve its display name.
                    command_data.Base_Sprite = 1;

                    // Get the bustup data for the first sprite and render the display name to the template.
                    bustup_data = BustupDataMethods.Get_Bustup_Data(account, set_data, command_data);
                    //graphics.DrawImage(Text_To_Blue(Render_Name(bustup_data)), 0, 0, template_width, template_height);
                }

                // Draw the input dialogue to the template.
                //graphics.DrawImage(Render_Dialogue(Line_Parser(sl_command, command_data.Dialogue)), 0, 0, template_width, template_height);
            }

            // Save the entire base template to a data stream.
            MemoryStream memoryStream = new MemoryStream();

            base_template.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Png);
            memoryStream.Seek(0, SeekOrigin.Begin);

            try
            {
                // Send the image.
                await sl_command.Channel.SendFileAsync(memoryStream, $"scene_{sl_command.User.Id}_{DateTime.UtcNow}.png");
            }
            catch (Exception e)
            {
                Console.WriteLine(e);

                // Send an error message to the user if the image upload fails.
                _ = ErrorHandling.Image_Upload_Failed(sl_command);

                // Clean up resources used by the stream, delete the loading message, and return.
                memoryStream.Dispose();
                await loader.DeleteAsync();

                return;
            }

            // Clean up resources used by the stream and delete the loading message.
            memoryStream.Dispose();
            await loader.DeleteAsync();

            // If the user has auto-delete for their commands set to on, delete their command as well.
            if (account.Auto_Delete_Commands == "On")
            {
                await sl_command.Message.DeleteAsync();
            }
        }