Compare commits

...

5 Commits
0.2.1 ... main

Author SHA1 Message Date
KikooDX ab7fa16727 fix: remove duplicate 'src/main.c' instance in meson.build 2021-05-23 12:50:03 +02:00
KikooDX 53132075b8 replace cmake with meson & use C99 instead of C89
This commit also takes care of all the warnings that didn't appear
with CMake. I decided to switch to C99 cause my code clearly wasn't
C89 compliant.
2021-05-04 22:32:37 +02:00
KikooDX 5727f19fb9 feature: window resizing (#1) 2021-04-17 17:22:41 +02:00
KikooDX dc7161c81b include/conf.h: use less specific values 2021-04-10 11:46:02 +02:00
KikooDX 023ff12cb9 Feature: middle click in editor to pick a tile
Updated the README in consequence.
2021-04-10 11:42:22 +02:00
14 changed files with 223 additions and 78 deletions

2
.gitignore vendored
View File

@ -1,4 +1,4 @@
build/
builddir/
# KBLE (Zig) files
backup_*.kble

View File

@ -1,32 +0,0 @@
cmake_minimum_required(VERSION 3.18)
project(sle C)
include_directories(include)
set(SOURCES
src/main.c
src/options.c
src/mouse.c
src/strtoint.c
src/strtocolor.c
src/editing_area/main.c
src/editing_area/level.c
src/editing_area/draw.c
src/tile_picker/main.c
src/tile_picker/draw.c
)
set(FLAGS
-Wall -Wextra -Wshadow -Wswitch-default -Wswitch-enum
-Wunreachable-code -Wstrict-prototypes -Wmissing-prototypes
-Wold-style-definition -Werror-implicit-function-declaration
-Wformat-pedantic
-Werror -pedantic -std=c90
-Os)
add_executable(${PROJECT_NAME} ${SOURCES} ${SOURCES_RAYLIB})
add_compile_options(PRIVATE ${FLAGS})
target_link_libraries(${PROJECT_NAME} raylib)

25
README
View File

@ -3,22 +3,26 @@ SLE
A simple project oriented single screen tilebased level editor.
SLE read and write KBLE level files.
=> https://git.sr.ht/~kikoodx/kble
KBLE format specifications:
=> https://git.sr.ht/~kikoodx/kble/tree/dev/item/kbleformat.md
COMPILATION
===========
Dependencies: raylib
Runtime dependencies: raylib
Build dependencies: meson, raylib
$ git clone https://git.sr.ht/~kikoodx/sle
$ mkdir sle/build && cd sle/build
$ cmake ..
$ make
$ git clone https://git.sr.ht/~kikoodx/sle && cd sle
$ meson setup builddir && cd builddir
$ meson compile
The following will install the resulting `sle` binary on your system.
# meson install
RUN
===
$ <SLE binary path> -tileset <tileset> -level <KBLE level to open>
Example:
$ build/sle -tileset assets/tileset.png -level sample.kble
$ sle -tileset assets/tileset.png -level sample.kble
SYNOPSIS
========
@ -34,6 +38,7 @@ Main window - Editing Area
--------------------------
Left click: draw with selected tile
Right click: erase (tile 0)
Middle click: pick a tile
Secondary window - Tile Picker
------------------------------
@ -50,8 +55,8 @@ FLAGS
Mandatory flags
---------------
All these options take a path to a file as argument.
-tileset Tileset image
-level KBLE file
-tileset : tileset image
-level : KBLE file
Optional flags
--------------
@ -65,9 +70,11 @@ These flags take integers as argument.
-level-width : used by -create
-level-height : used by -create
-tile-first
-editor-scale
-editor-width
-editor-height
-editor-target-fps
-editor-scale
-editor-off-x
-editor-off-y
-picker-target-fps

View File

@ -17,16 +17,18 @@
#define OVERRING_TILE_COLOR \
(Color) { 255, 255, 255, 80 }
#define NEW_LEVEL_WIDTH 25
#define NEW_LEVEL_HEIGHT 14
#define NEW_LEVEL_WIDTH 32
#define NEW_LEVEL_HEIGHT 18
#define EDITOR_WINDOW_WIDTH 396
#define EDITOR_WINDOW_HEIGHT 224
#define EDITOR_SCALE 2
#define EDITOR_WINDOW_WIDTH 512
#define EDITOR_WINDOW_HEIGHT 288
#define EDITOR_TARGET_FPS 60
#define EDITOR_DRAW_OFFSET_X -2
#define EDITOR_DRAW_OFFSET_X 0
#define EDITOR_DRAW_OFFSET_Y 0
#define PICKER_TARGET_FPS 30
#define PICKER_SCALE 2
#define PICKER_TARGET_FPS 60
#define PICKER_PADDING 4
#define PICKER_WINDOW_WIDTH \

View File

@ -16,12 +16,14 @@ struct Options {
int tile_first;
int new_level_width;
int new_level_height;
int editor_scale;
int editor_width;
int editor_height;
int editor_target_fps;
int editor_draw_offset_x;
int editor_draw_offset_y;
Color editor_bg_color;
int picker_scale;
int picker_target_fps;
int picker_padding;
Color picker_bg_color;

11
include/scale.h Normal file
View File

@ -0,0 +1,11 @@
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2021 KikooDX */
#pragma once
#include "options.h"
#include <raylib.h>
float scale_editor(struct Options options);
Vector2 offset_editor(struct Options options);
float scale_picker(struct Options options);
Vector2 offset_picker(struct Options options);

43
meson.build Normal file
View File

@ -0,0 +1,43 @@
project('sle', 'c',
version : '0.4.0',
license : 'GPL-3.0-or-later')
raylibdep = dependency('raylib', version: '>=3.5.0')
inc = include_directories('include')
sources = [
'src/main.c',
'src/mouse.c',
'src/options.c',
'src/scale.c',
'src/strtocolor.c',
'src/strtoint.c',
'src/editing_area/draw.c',
'src/editing_area/level.c',
'src/editing_area/main.c',
'src/tile_picker/draw.c',
'src/tile_picker/main.c',
]
c_flags = [
'-std=c99',
'-Os',
'-Wall',
'-Wextra',
'-pedantic',
'-Wshadow',
'-Wswitch-default',
'-Wswitch-enum',
'-Wunreachable-code',
'-Wstrict-prototypes',
'-Wmissing-prototypes',
'-Wold-style-definition',
'-Werror-implicit-function-declaration',
]
executable('sle',
sources,
include_directories : inc,
dependencies : raylibdep,
install : true,
c_args : c_flags)

View File

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2021 KikooDX */
#include "editing_area/draw.h"
#include "conf.h"
#include "editing_area/level.h"
#include "options.h"
@ -18,10 +19,12 @@ void level_draw(struct Level level, struct Options options,
/* if tile index is out of bound, skip */
if (tile_index >= level.width * level.height)
continue;
const Tile tile = level.data[tile_index] - options.tile_first;
const Tile tile =
level.data[tile_index] - options.tile_first;
/* if tile is not in tileset, skip */
if (tile < 0 || (!tile && !options.tile_first) || tile >= options.tileset_width *
options.tileset_height)
if ((!tile && !options.tile_first) ||
tile >= (Tile)options.tileset_width *
options.tileset_height)
continue;
const Rectangle tile_rect = {

View File

@ -18,6 +18,7 @@ static int write_byte_group(FILE *file, Tile value, int size);
int level_read(struct Level *level, char *path)
{
FILE *file = NULL;
int byte_hold = 0;
unsigned char byte = 0;
unsigned int tile_size = 0;
int level_size = 0;
@ -43,9 +44,10 @@ int level_read(struct Level *level, char *path)
}
/* get tile size (in bytes) */
tile_size = read_byte(file);
if (tile_size < 0)
byte_hold = read_byte(file);
if (byte_hold < 0)
return -1;
tile_size = (unsigned int)byte_hold;
/* check than tile size is in boundaries */
if (tile_size > sizeof(Tile) / sizeof(char)) {
fprintf(stderr,
@ -56,11 +58,11 @@ int level_read(struct Level *level, char *path)
}
/* get width */
level->width = read_byte_group(file, 2);
if (level->width == (Tile)-1)
if ((Tile)level->width == (Tile)-1)
return -1;
/* get height */
level->height = read_byte_group(file, 2);
if (level->height == (Tile)-1)
if ((Tile)level->height == (Tile)-1)
return -1;
/* allocate memory for data */
@ -96,11 +98,11 @@ int level_create(struct Level *level, struct Options options)
/* set width */
level->width = options.new_level_width;
if (level->width == (Tile)-1)
if ((Tile)level->width == (Tile)-1)
return -1;
/* set height */
level->height = options.new_level_height;
if (level->height == (Tile)-1)
if ((Tile)level->height == (Tile)-1)
return -1;
/* allocate memory for data */

View File

@ -1,12 +1,14 @@
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2021 KikooDX */
#include "editing_area/main.h"
#include "conf.h"
#include "editing_area/draw.h"
#include "editing_area/level.h"
#include "info.h"
#include "mouse.h"
#include "options.h"
#include "scale.h"
#include "shared_data.h"
#include <raylib.h>
#include <stdbool.h>
@ -23,19 +25,25 @@ int editing_area_main(struct Options options,
{
int mouse_x;
int mouse_y;
int error;
struct Level level;
level.data = NULL;
Texture2D tileset;
/* initialize raylib */
InitWindow(options.editor_width, options.editor_height,
InitWindow(options.editor_width * options.editor_scale,
options.editor_height * options.editor_scale,
"SLE main window");
SetWindowState(FLAG_WINDOW_RESIZABLE);
SetTargetFPS(options.editor_target_fps);
init_mouse(options);
/* load textures */
tileset = LoadTexture(options.tileset_path);
/* render targets used for upscaling */
const RenderTexture2D rend_target = LoadRenderTexture(
options.editor_width, options.editor_height);
const RenderTexture2D flip_target = LoadRenderTexture(
options.editor_width, options.editor_height);
/* only proceed if tileset is large enough */
if (tileset.width < options.tile_width ||
tileset.height < options.tile_height) {
@ -56,15 +64,29 @@ int editing_area_main(struct Options options,
while (!WindowShouldClose()) {
/* update */
init_mouse(options);
update_mouse(&mouse_x, &mouse_y, level, shared_data);
/* draw */
BeginDrawing();
BeginTextureMode(rend_target);
ClearBackground(options.editor_bg_color);
level_draw(level, options, tileset);
editor_mouse_draw(options, mouse_x, mouse_y);
EndTextureMode();
/* flip texture */
BeginTextureMode(flip_target);
DrawTexture(rend_target.texture, 0, 0, WHITE);
EndTextureMode();
/* draw upscaled render */
ClearBackground(BLACK);
DrawTextureEx(flip_target.texture,
offset_editor(options), 0,
scale_editor(options), WHITE);
EndDrawing();
}
@ -76,8 +98,10 @@ panic:
/* deinit */
level_free(&level);
/* unload textures */
/* unload raylib stuff */
UnloadTexture(tileset);
UnloadRenderTexture(rend_target);
UnloadRenderTexture(flip_target);
CloseWindow();
/* tell to the child process it can end */
@ -91,10 +115,12 @@ panic:
static void init_mouse(struct Options options)
{
SetMouseOffset(-options.editor_draw_offset_x,
-options.editor_draw_offset_y);
SetMouseScale(1.0 / options.tile_width,
1.0 / options.tile_height);
const float scaling = scale_editor(options);
const Vector2 off = offset_editor(options);
SetMouseOffset(-options.editor_draw_offset_x - off.x,
-options.editor_draw_offset_y - off.y);
SetMouseScale(1.0 / scaling / options.tile_width,
1.0 / scaling / options.tile_height);
}
static void update_mouse(int *mouse_x, int *mouse_y, struct Level level,
@ -108,17 +134,17 @@ static void update_mouse(int *mouse_x, int *mouse_y, struct Level level,
level.height - 1);
/* set tile */
if (left_click) {
if (left_click)
level.data[*mouse_x + *mouse_y * level.width] =
shared_data->selected_tile;
}
/* remove tile */
if (right_click) {
if (right_click)
level.data[*mouse_x + *mouse_y * level.width] = 0;
}
/* get info about tile */
/* set tile to pointed cell (pick tile) */
if (middle_click) {
INFO_VAR("%d",
level.data[*mouse_x + *mouse_y * level.width]);
shared_data->selected_tile =
level.data[*mouse_x + *mouse_y * level.width];
}
}

View File

@ -32,7 +32,6 @@ static void set_tileset_dimensions(struct Options *options);
* organize these panels in the way they want to. */
int main(int argc, char **argv)
{
int error;
pid_t child_process;
struct SharedData *shared_data;
struct Options options = options_defaults();
@ -102,12 +101,14 @@ static void process_arguments(int argc, char **argv,
{"tile-first", required_argument, 0, 'I'},
{"level-width", required_argument, 0, 'i'},
{"level-height", required_argument, 0, 'e'},
{"editor-scale", required_argument, 0, 's'},
{"editor-width", required_argument, 0, 'W'},
{"editor-height", required_argument, 0, 'H'},
{"editor-fps", required_argument, 0, 'f'},
{"editor-off-x", required_argument, 0, 'o'},
{"editor-off-y", required_argument, 0, 'O'},
{"editor-bg-color", required_argument, 0, 'b'},
{"picker-scale", required_argument, 0, 'S'},
{"picker-fps", required_argument, 0, 'F'},
{"picker-padding", required_argument, 0, 'p'},
{"picker-bg-color", required_argument, 0, 'B'},
@ -146,6 +147,9 @@ static void process_arguments(int argc, char **argv,
case 'e': /* new level height */
options->new_level_height = int_arg_min(opt, 1);
break;
case 's': /* editor scale */
options->editor_scale = int_arg_min(opt, 1);
break;
case 'W': /* editor width */
options->editor_width = int_arg_min(opt, 1);
break;
@ -167,6 +171,9 @@ static void process_arguments(int argc, char **argv,
case 'b': /* editor background color */
options->editor_bg_color = strtocolor(optarg);
break;
case 'S': /* picker scale */
options->picker_scale = int_arg_min(opt, 1);
break;
case 'F': /* picker target FPS */
options->picker_target_fps =
int_arg_min(opt, 1);

View File

@ -13,12 +13,14 @@ struct Options options_defaults(void)
.tileset_height = 0,
.new_level_width = NEW_LEVEL_WIDTH,
.new_level_height = NEW_LEVEL_HEIGHT,
.editor_scale = EDITOR_SCALE,
.editor_width = EDITOR_WINDOW_WIDTH,
.editor_height = EDITOR_WINDOW_HEIGHT,
.editor_target_fps = EDITOR_TARGET_FPS,
.editor_draw_offset_x = EDITOR_DRAW_OFFSET_X,
.editor_draw_offset_y = EDITOR_DRAW_OFFSET_Y,
.editor_bg_color = EDITOR_BACKGROUND_COLOR,
.picker_scale = PICKER_SCALE,
.picker_window_width = 0,
.picker_window_height = 0,
.picker_target_fps = PICKER_TARGET_FPS,

46
src/scale.c Normal file
View File

@ -0,0 +1,46 @@
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2021 KikooDX */
#include "scale.h"
#include "options.h"
#include <raylib.h>
float scale_editor(struct Options options)
{
const float w_ratio =
(float)GetScreenWidth() / options.editor_width;
const float h_ratio =
(float)GetScreenHeight() / options.editor_height;
return (w_ratio < h_ratio) ? w_ratio : h_ratio;
}
Vector2 offset_editor(struct Options options)
{
const float scaling = scale_editor(options);
return (Vector2){
((float)GetScreenWidth() - options.editor_width * scaling) /
2,
((float)GetScreenHeight() -
options.editor_height * scaling) /
2};
}
float scale_picker(struct Options options)
{
const float w_ratio =
(float)GetScreenWidth() / options.picker_window_width;
const float h_ratio =
(float)GetScreenHeight() / options.picker_window_height;
return (w_ratio < h_ratio) ? w_ratio : h_ratio;
}
Vector2 offset_picker(struct Options options)
{
const float scaling = scale_picker(options);
return (Vector2){((float)GetScreenWidth() -
options.picker_window_width * scaling) /
2,
((float)GetScreenHeight() -
options.picker_window_height * scaling) /
2};
}

View File

@ -1,9 +1,11 @@
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright (C) 2021 KikooDX */
#include "tile_picker/main.h"
#include "conf.h"
#include "mouse.h"
#include "options.h"
#include "scale.h"
#include "shared_data.h"
#include "tile_picker/draw.h"
#include <raylib.h>
@ -24,28 +26,48 @@ int tile_picker_main(struct Options options,
Texture2D tileset;
/* initialize raylib */
InitWindow(options.picker_window_width,
options.picker_window_height,
InitWindow(options.picker_window_width * options.picker_scale,
options.picker_window_height * options.picker_scale,
"SLE secondary window");
SetTargetFPS(options.picker_target_fps);
init_mouse(options);
/* load textures */
tileset = LoadTexture(options.tileset_path);
/* render targets used for upscaling */
const RenderTexture2D rend_target = LoadRenderTexture(
options.picker_window_width, options.picker_window_height);
const RenderTexture2D flip_target = LoadRenderTexture(
options.picker_window_width, options.picker_window_height);
/* only proceed if tileset is well loaded */
if (tileset.width > 0) {
while (!shared_data->end_child) {
/* update */
init_mouse(options);
update_mouse(&mouse_x, &mouse_y, options,
shared_data);
/* draw */
BeginDrawing();
BeginTextureMode(rend_target);
ClearBackground(options.picker_bg_color);
tileset_draw(tileset, options,
shared_data->selected_tile);
EndTextureMode();
/* flip texture */
BeginTextureMode(flip_target);
DrawTexture(rend_target.texture, 0, 0, WHITE);
EndTextureMode();
/* draw upscaled render */
ClearBackground(BLACK);
DrawTextureEx(flip_target.texture,
offset_picker(options), 0,
scale_picker(options), WHITE);
EndDrawing();
}
}
@ -60,11 +82,15 @@ int tile_picker_main(struct Options options,
static void init_mouse(struct Options options)
{
SetMouseOffset(-options.picker_padding,
-options.picker_padding);
const float scaling = scale_picker(options);
const Vector2 off = offset_picker(options);
SetMouseOffset(-options.picker_padding - off.x,
-options.picker_padding - off.y);
SetMouseScale(
1.0 / (options.tile_width + options.picker_padding),
1.0 / (options.tile_height + options.picker_padding));
1.0 / (options.tile_width + options.picker_padding) /
scaling,
1.0 / (options.tile_height + options.picker_padding) /
scaling);
}
static void update_mouse(int *mouse_x, int *mouse_y,
@ -72,7 +98,7 @@ static void update_mouse(int *mouse_x, int *mouse_y,
struct SharedData *shared_data)
{
const bool left_click = IsMouseButtonDown(0);
const bool right_click = IsMouseButtonDown(1);
/* const bool right_click = IsMouseButtonDown(1); */
update_mouse_position(
mouse_x, mouse_y,