Why does my texture packer not find the sprites? - libgdx

Im using the TexturePacker implemented by LibGDX to load my sprites.
For some reason however, the files are not found and it gives me this exception:
Exception in thread "main" java.lang.RuntimeException: Error packing images.
at com.badlogic.gdx.tools.texturepacker.TexturePacker.process(TexturePacker.java:620)
at com.zebleck.OneRoom.desktop.DesktopLauncher.processSprites(DesktopLauncher.java:35)
at com.zebleck.OneRoom.desktop.DesktopLauncher.main(DesktopLauncher.java:17)
Caused by: java.lang.IllegalArgumentException: Input file does not exist: C:\Users\Kontor\Desktop\Codeporn\LibGDX-workspace\OneRoom\desktop\sprites\input
at com.badlogic.gdx.tools.FileProcessor.process(FileProcessor.java:117)
at com.badlogic.gdx.tools.texturepacker.TexturePackerFileProcessor.process(TexturePackerFileProcessor.java:70)
at com.badlogic.gdx.tools.texturepacker.TexturePacker.process(TexturePacker.java:618)
... 2 more
This code is causing the error:
public static void main (String[] arg) {
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
config.width = 800;
config.height = 800;
deleteFiles();
processSprites();
new LwjglApplication(new OneRoom(), config);
}
public static void deleteFiles() {
File outputDir = new File("../android/assets/sprites/output");
File[] listFiles = outputDir.listFiles();
if (listFiles != null && listFiles.length > 0) {
for (File file : listFiles) {
file.delete();
}
}
}
public static void processSprites() {
TexturePacker.Settings settings = new TexturePacker.Settings();
//System.out.println(Gdx.files.internal("sprites/input/player.png").toString());
TexturePacker.process(settings, "sprites/input", "sprites/output", "pack"); // THIS LINE CAUSES THE ERROR
}
I also got the EXACT same code in another project and it works just fine. I haven't found any differences in the project properties yet.

Make sure the sprites actually exist in that directory.
Sounds patronising but I was having the same issue and for me I was being misled by my assets directory in my desktop project being a "Linked Folder" that was actually just a reference to the assets folder of my core project. So in eclipse the folder is there and looks like there should be no problem but looking through windows file explorer it was clear the files didn't actually exist at that location.
My fix was to change the input and output to step back and check the core directory instead of the desktop.
So instead of:
TexturePacker.process(settings, "sprites/input", "sprites/output", "pack");
The following would work:
TexturePacker.process(settings, "../core/sprites/input", "../core/sprites/output", "pack");
Now I don't know your exact setup but considering your code works in a different project I would wager that the other project has the assets actually stored in the desktop directory where as this one stores the images in the core directory.

Related

Enforce Microsoft.Build to reload the project

I'm trying to iteratively (part of automation):
Create backup of the projects in solution (physical files on the filesystem)
Using Microsoft.Build programmatically load and change projects inside of the solution (refernces, includes, some other properties)
Build it with console call of msbuild
Restore projects (physically overriding patched versions from backups)
This approach works well for first iteration, but for second it appears that it does not load restored projects and trying to work with values that I patched on the first iteration. It looks like projects are cached: inside of the csproj files I see correct values, but on the code I see previously patched values.
My best guess is that Microsoft.Build is caching solution/projects in the context of the current process.
Here is code that is responsible to load project and call method to update project information:
private static void ForEachProject(string slnPath, Func<ProjectRootElement> patchProject)
{
SolutionFile slnFile = SolutionFile.Parse(slnPath);
var filtredProjects = slnFile
.ProjectsInOrder
.Where(prj => prj.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat);
foreach (ProjectInSolution projectInfo in filtredProjects)
{
try
{
ProjectRootElement project = ProjectRootElement.Open(projectInfo.AbsolutePath);
patchProject(project);
project.Save();
}
catch (InvalidProjectFileException ex)
{
Console.WriteLine("Failed to patch project '{0}' with error: {1}", projectInfo.AbsolutePath, ex);
}
}
}
There is Reload method for the ProjectRootElement that migh be called before iteraction with content of the project.
It will enforce Microsoft.Build to read latest information from the file.
Code that is working for me:
private static void ForEachProject(string slnPath, Func<ProjectRootElement> patchProject)
{
SolutionFile slnFile = SolutionFile.Parse(slnPath);
var filtredProjects = slnFile
.ProjectsInOrder
.Where(prj => prj.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat);
foreach (ProjectInSolution projectInfo in filtredProjects)
{
try
{
ProjectRootElement project = ProjectRootElement.Open(projectInfo.AbsolutePath);
project.Reload(false); // Ignore cached state, read actual from the file
patchProject(project);
project.Save();
}
catch (InvalidProjectFileException ex)
{
Console.WriteLine("Failed to patch project '{0}' with error: {1}", projectInfo.AbsolutePath, ex);
}
}
}
Note: It better to use custom properties inside of the project and provide it for each msbuild call instead of physical project patching. Please consider it as better solution and use it if possible.

Child process of .net core application is using parent's configuration file

I have 2 .NET Core 2.0 console applications. The first application calls the second one via System.Diagnostics.Process.Start(). Somehow the second app is inheriting the development configuration information located in the appsettings.development.json of the first app.
I execute the first app by running either dotnet run in the root of the project or dotnet firstapp.dll in the folder where the DLL exists. This is started from in Powershell.
Both apps are separate directories. I'm not sure how this is happening.
UPDATE WITH CODE
The apps reside in
C:\Projects\ParentConsoleApp
C:\Projects\ChildConsoleApp
This is how I call the app from parent application:
System.Diagnostics.Process.Start("dotnet", "C:\\projects\\ChildConsoleApp\\bin\\Debug\\netcoreapp2.0\\publish\\ChildConsoleApp.dll" + $" -dt {DateTime.Now.Date.ToString("yyyy-MM-dd")}");
This is how I load the configuration from JSON (this is same in both apps):
class Program
{
private static ILogger<Program> _logger;
public static IConfigurationRoot _configuration;
public static IServiceProvider Container { get; private set; }
static void Main(string[] args)
{
RegisterServices();
_logger = Container.GetRequiredService<ILogger<Program>>();
_logger.LogInformation("Starting GICMON Count Scheduler Service");
Configure();
// At this point DBContext has value from parent! :(
var repo = Container.GetService<ICountRepository>();
var results = repo.Count(_configuration.GetConnectionString("DBContext"), args[0]);
}
private static void Configure()
{
string envvar = "DOTNET_ENVIRONMENT";
string env = Environment.GetEnvironmentVariable(envvar);
if (String.IsNullOrWhiteSpace(env))
throw new ArgumentNullException("DOTNET_ENVIRONMENT", "Environment variable not found.");
_logger.LogInformation($"DOTNET_ENVIRONMENT environment variable value is: {env}.");
var builder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json");
if (!String.IsNullOrWhiteSpace(env)) // environment == "Development"
{
builder.AddJsonFile($"appsettings.{env}.json", optional: true);
}
_configuration = builder.Build();
}
private static void RegisterServices()
{
var services = new ServiceCollection();
services.AddSingleton<ILoggerFactory, LoggerFactory>();
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));
services.AddLogging((builder) => builder.SetMinimumLevel(LogLevel.Trace));
var serviceProvider = services.BuildServiceProvider();
var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
loggerFactory.AddNLog(new NLogProviderOptions { CaptureMessageTemplates = true, CaptureMessageProperties = true });
loggerFactory.ConfigureNLog("nlog.config");
Container = serviceProvider;
}
}
The problem is caused by the fact that you set base path for configuration builder to the current working directory:
var builder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json");
When you create a child process, it inherits current directory from the parent process (unless you set current directory explicitly).
So the child process basically uses JSON configs from the directory of parent process.
There are several possible fixes:
Do not set base path to the current directory.
When the application is launched, you don't know for sure that current directory will match directory where application binaries are placed.
If you have an exe file in c:\test\SomeApp.exe and launch it from the command line while the current directory is c:\, then current directory of your application will be c:\. In this case, if you set base path for configuration builder to current directory, it will not be able to load configuration files.
By default, configuration builder loads config files from AppContext.BaseDirectory which is the directory where application binaries are placed. It should be desired behavior in most cases.
So just remove SetBasePath() call:
var builder = new ConfigurationBuilder().AddJsonFile("appsettings.json");
If for some reason you want to set the base path of configuration builder to the current directory, then you should set correct current directory for the launched child process:
var childDllPath = "C:\\projects\\ChildConsoleApp\\bin\\Debug\\netcoreapp2.0\\publish\\ChildConsoleApp.dll";
var startInfo = new ProcessStartInfo("dotnet", childDllPath + $" -dt {DateTime.Now.Date.ToString("yyyy-MM-dd")}")
{
WorkingDirectory = Path.GetDirectoryName(childDllPath),
};
Process.Start(startInfo);
As #CodeFuller explained, the reason is that both apps read the same appsettings.{env}.json file. For simplicity, you may just rename the config file (and the corresponding name in .AddJsonFile) for the second app to prevent any possible overrides.
See, when you register JSON file as a configuration source by .AddJsonFile, configuration API allows you to use whatever file name you need and
you are not forced to use the same $"appsettings.{env}.json" pattern for both applications.

Razor engine cant find view

I'm trying to render a HTML from a view without using a web request. I need the HTML as a string, internally, I do not wish to serve it.
The viewEngine.FindView() returns a viewEnineResult that shows no view was found. It shows to search locations where it looked they look like this:
/Views//PDFOperationsReportView.cshtml
/Views/Shared/PDFOperationsReportView.cshtml
(Observe the double forward slash in the first line)
File structure (I placed it into a HTML snippet cause I couldn't manage to format the text properly in this editor)
Project
Folder
Subfolder
CodeFile.cs
Views
PDFOperationsReportView.cshtml
The code:
var viewName = "PDFOperationsReportView";
var actionContext = GetActionContext();
var viewEngineResult = _viewEngine.FindView(actionContext, viewName, false);
if (!viewEngineResult.Success)
{
throw new InvalidOperationException(string.Format("Couldn't find view '{0}'", viewName));
}
var view = viewEngineResult.View;
I had the same issue. I found the answer here: GitHub aspnet/Mvc Issue #4936
Basically, use GetView instead of FindView, like this:
var viewResult = razorViewEngine.GetView(viewName, viewName, false);
Your viewName needs to be a full path for this to work. For example:
/Views/Shared/PDFOperationsReportView.cshtml
~/Pages/Shared/_Article.cshtml
~/Areas/CM/Pages/_Article.cshtml
We have a helper method defined to render optional views which may or may not exist:
public static Task RenderPartialAsyncIfExists(this IHtmlHelper htmlHelper, ICompositeViewEngine engine, string partialViewName, object model)
{
if (engine.GetView(partialViewName, partialViewName, false).Success)
{
return htmlHelper.RenderPartialAsync(partialViewName, model);
}
return Task.CompletedTask;
}
It's used on view pages like:
#inject ICompositeViewEngine Engine
...
#{ await Html.RenderPartialAsyncIfExists(Engine, $"~/Views/Shared/_navigationAdmin.cshtml"); }
This works find locally (IIS Express) but for some reason was failing when deployed to IIS.
In my case, there was something wrong with the .csproj file, where the view in question was removed but then re-added as an embedded resource:
<ItemGroup>
<Content Remove="Views\Shared\_navigationAdmin.cshtml" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Views\Shared\_navigationAdmin.cshtml" />
</ItemGroup>
Removing those two sections from the .csproj fixed the problem in IIS.
This is using (EOL) AspNet Core 2.2

How do I allow an MIME extension map in ASP.NET vNext?

Background
I have a piece of LESS code that needs to be compiled at runtime with Less.js -- it calculates some things via JavaScript -- so I can't use the task runner, etc.
In my index.html, I have:
<head>
...
<link rel="stylesheet/less" href="assets/less/DynamicHeight.less" />
...
<script type="text/javascript" src="lib/less/less.js"></script>
...
</head>
Problem
Less.js appears unable to find the file:
And when I try to access the file directly, I see:
Question
How can I add the configuration that will allow this less file to be downloaded? Am I still able to use web.config files with vNext, or do I need to do something with config.json instead?
Lead 1: Should I use Owin?
Thinking this might be the right path but I'm pretty unfamiliar.
I see a number of tutorials out there, such as K. Scott Allen's, which reference code such as:
public void Configuration(IAppBuilder app)
{
var options = new StaticFileOptions
{
ContentTypeProvider = new FileExtensionContentTypeProvider()
};
((FileExtensionContentTypeProvider)options.ContentTypeProvider).Mappings.Add(
new KeyValuePair<string, string>(".less", "text/css"));
app.UseStaticFiles(options);
}
However, it appears that in its current version, asp.net is looking for a signature of Configure(IApplicationBuilder app) instead.
The IApplicationBuilder class doesn't have a method along the lines of UseStaticFiles -- it only has a signature of IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware).
I have a feeling that this is likely the right path to solve the issue -- I just can't find out how to propertly configure the IAppliationBuilder to map the MIME extension.
Okay, I believe I figured it out.
Step 1: Add the appropriate library for static files
In ASP.NET vNext, this is Microsoft.Aspnet.StaticFiles.
In your project.json file, add the following under "dependencies":
"Microsoft.AspNet.StaticFiles": "1.0.0-beta2"
This adds the static middleware method that you can use later.
Step 2: Configure the app to use Static Files
Add the using statement at the top:
using Microsoft.AspNet.StaticFiles;
At this point, the app.UseStaticFiles method will be available, so your Configure method can look as follows:
public void Configure(IApplicationBuilder app)
{
var options = new StaticFileOptions
{
ContentTypeProvider = new FileExtensionContentTypeProvider()
};
((FileExtensionContentTypeProvider)options.ContentTypeProvider).Mappings.Add(
new KeyValuePair<string, string>(".less", "text/css"));
app.UseStaticFiles(options);
}
And voila! I get text when browsing to .less files, and no more error is appearing from LessJS.
In .NET Core 1.0.1, SeanKileen answer is still good. The following is a simple code rewrite:
public void Configure(IApplicationBuilder app, ...)
var contentTypeProvider = new FileExtensionContentTypeProvider();
contentTypeProvider.Mappings[".map"] = "application/javascript";
contentTypeProvider.Mappings[".less"] = "text/css";
app.UseStaticFiles(new StaticFileOptions()
{
ContentTypeProvider = contentTypeProvider
});
The above code EXTENDS the default mapping list (see the source), which already has ~370 mappings.
Avoid using the FileExtensionContentTypeProvider constructor overload that takes a dictionary (as suggested by JHo) if you want those 370 default mappings.
SeanKilleen's answer is right on, and still works ASP.NET Core RC1. My only improvement is to write the exact same code using collection initializers to make it cleaner.
app.UseStaticFiles(new StaticFileOptions
{
ContentTypeProvider = new FileExtensionContentTypeProvider(new Dictionary<string, string>
{
{ ".less", "text/css" },
{ ".babylon", "text/json" },
// ....
})
});

How would you simplify this process?

I have a bunch (over 1000) HTML files with just simple text. It's just a combination of text within a <table>. It's an internal batch of documents, not for web production.
The job we have is to convert them into JPEG files using Photoshop and the old copy paste method. It's tedious.
Is there a way you would do this process to make it more efficient/easier/simple?
I thought about trying to convert the HTML into Excel and then mail merging it into Word to print as JGEG. But I can't find (and rightly so) anything to convert HTML to XLSX.
Thoughts? Or is this just a manual job?
Here's a little something I created to convert a single html file to jpeg. It's not pretty (to say the least), but it works fine with a table larger than my screen. Put it inside a windows forms project. You can add more checks and call this program in a loop, or refactor it to work on multiple html files.
Ideas and techniques taken from -
Finding the needed size - http://social.msdn.microsoft.com/Forums/ie/en-US/f6f0c641-43bd-44cc-8be0-12b40fbc4c43/webbrowser-object-use-to-find-the-width-of-a-web-page
Creating the graphics - http://cplus.about.com/od/learnc/a/How-To-Save-Web-Page-Screen-Grab-csharp.htm
A table for example - copy-paste enlarged version of http://www.w3schools.com/html/html_tables.asp
static class Program
{
static WebBrowser webBrowser = new WebBrowser();
private static string m_fileName;
[STAThread]
static void Main(string[] args)
{
if (args.Length != 1)
{
MessageBox.Show("Usage: [fileName]");
return;
}
m_fileName = args[0];
webBrowser.DocumentCompleted += (a, b) => webBrowser_DocumentCompleted();
webBrowser.ScrollBarsEnabled = false; // Don't want them rendered
webBrowser.Navigate(new Uri(m_fileName));
Application.Run();
}
static void webBrowser_DocumentCompleted()
{
// Get the needed size of the control
webBrowser.Width = webBrowser.Document.Body.ScrollRectangle.Width + webBrowser.Margin.Horizontal;
webBrowser.Height = webBrowser.Document.Body.ScrollRectangle.Height + webBrowser.Margin.Vertical;
// Create the graphics and save the image
using (var graphics = webBrowser.CreateGraphics())
{
var bitmap = new Bitmap(webBrowser.Size.Width, webBrowser.Size.Height, graphics);
webBrowser.DrawToBitmap(bitmap, webBrowser.ClientRectangle);
string newFileName = Path.ChangeExtension(m_fileName, ".jpg");
bitmap.Save(newFileName, ImageFormat.Jpeg);
}
// Shamefully exit the application
Application.ExitThread();
}
}
You can load all files in one page and use this lib html2canvas to covert.
You can running in the background use nodejs with node-canvas or make it a desk app with node-webkit
In case anyone was looking for answer that works, I ended up using a program called Prince: https://www.princexml.com
It works amazingly, and just have to target the HTML with CSS or JS to make it match your output!