Add MLX42 V2
This commit is contained in:
parent
8ff4363d2c
commit
bc5fc2fc59
1
MLX42
1
MLX42
@ -1 +0,0 @@
|
|||||||
Subproject commit 5ba2f30e0fbb42ff079960528768cfbc10a0f218
|
|
8
MLX42/.gitattributes
vendored
Normal file
8
MLX42/.gitattributes
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# See https://docs.github.com/en/get-started/getting-started-with-git/configuring-git-to-handle-line-endings
|
||||||
|
|
||||||
|
# Set the default behavior, in case people don't have core.autocrlf set
|
||||||
|
* text=auto
|
||||||
|
|
||||||
|
# Declare files that will always have a certain EOL
|
||||||
|
*.sh text eol=lf
|
||||||
|
shaders/** text eol=lf
|
34
MLX42/.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
34
MLX42/.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: "[BUG]"
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**NOTE**
|
||||||
|
Before creating a bug report! Make sure you git pull from master and check if the bug still exists!
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '...'
|
||||||
|
3. Scroll down to '...'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**Desktop (please complete the following information):**
|
||||||
|
- OS: [e.g. MacOS]
|
||||||
|
- Version: [e.g. BigSur]
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
20
MLX42/.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
MLX42/.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: "[REQUEST]"
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
78
MLX42/.github/workflows/ci.yml
vendored
Normal file
78
MLX42/.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Codam Coding College, Amsterdam @ 2022-2023-2023 by W2Wizard.
|
||||||
|
# See README in the root project for more information.
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
name: Build
|
||||||
|
|
||||||
|
#=============================================================================#
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
#=============================================================================#
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
#=============================================================================#
|
||||||
|
|
||||||
|
unit-test:
|
||||||
|
timeout-minutes: 10
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
DISPLAY: ":99"
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Clone repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update -qq
|
||||||
|
sudo apt-get install -y -qq xorg-dev xvfb
|
||||||
|
|
||||||
|
- name: Setup virtual screen
|
||||||
|
run: Xvfb $DISPLAY -screen 0 1280x1024x24 &
|
||||||
|
|
||||||
|
- name: Build MLX42 & tests
|
||||||
|
run: cmake -DBUILD_TESTS=YES -B ${{github.workspace}}/build && cmake --build ${{github.workspace}}/build --parallel
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: ctest --output-on-failure --test-dir ${{github.workspace}}/build
|
||||||
|
|
||||||
|
# Unix
|
||||||
|
#=============================================================================#
|
||||||
|
|
||||||
|
build:
|
||||||
|
timeout-minutes: 10
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Clone repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
# Windows will just fetch glfw with cmake automatically.
|
||||||
|
# This avoids doing extra work like installing a package manager.
|
||||||
|
- name: Install Dependencies
|
||||||
|
if: matrix.os != 'windows-latest'
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
if [ "$RUNNER_OS" == "Linux" ]; then
|
||||||
|
sudo apt-get update -qq
|
||||||
|
sudo apt-get install -y -qq xorg-dev
|
||||||
|
elif [ "$RUNNER_OS" == "macOS" ]; then
|
||||||
|
brew update
|
||||||
|
brew install glfw
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: cmake -B build && cmake --build build --parallel
|
||||||
|
|
||||||
|
#=============================================================================#
|
68
MLX42/.gitignore
vendored
Normal file
68
MLX42/.gitignore
vendored
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
# Prerequisites
|
||||||
|
*.d
|
||||||
|
|
||||||
|
# Object files
|
||||||
|
*.o
|
||||||
|
*.ko
|
||||||
|
*.obj
|
||||||
|
*.elf
|
||||||
|
|
||||||
|
# Linker output
|
||||||
|
*.ilk
|
||||||
|
*.map
|
||||||
|
*.exp
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Libraries
|
||||||
|
*.lib
|
||||||
|
*.a
|
||||||
|
*.la
|
||||||
|
*.lo
|
||||||
|
|
||||||
|
# Shared objects (inc. Windows DLLs)
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.so.*
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
*.app
|
||||||
|
*.i*86
|
||||||
|
*.x86_64
|
||||||
|
*.hex
|
||||||
|
|
||||||
|
# Debug files
|
||||||
|
*.dSYM/
|
||||||
|
*.su
|
||||||
|
*.idb
|
||||||
|
*.pdb
|
||||||
|
|
||||||
|
# Kernel Module Compile Results
|
||||||
|
*.mod*
|
||||||
|
*.cmd
|
||||||
|
.tmp_versions/
|
||||||
|
modules.order
|
||||||
|
Module.symvers
|
||||||
|
Mkfile.old
|
||||||
|
dkms.conf
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
main.c
|
||||||
|
temp/
|
||||||
|
.vscode/
|
||||||
|
lib/glfw/
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Special shader files
|
||||||
|
mlx_*_shader.c
|
||||||
|
build/
|
||||||
|
main.c
|
||||||
|
test
|
||||||
|
|
||||||
|
# Automatic downloaded deps
|
||||||
|
_deps/
|
156
MLX42/CMakeLists.txt
Normal file
156
MLX42/CMakeLists.txt
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Codam Coding College, Amsterdam @ 2022-2023 by W2Wizard.
|
||||||
|
# See README in the root project for more information.
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# CMake specifications
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
cmake_minimum_required (VERSION 3.18.0)
|
||||||
|
project(mlx42 VERSION 2.3.1)
|
||||||
|
message(STATUS "MLX42 @ ${CMAKE_PROJECT_VERSION}")
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||||
|
set(TOOLS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/tools)
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||||
|
set(CMAKE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||||
|
set(CMAKE_C_STANDARD 11)
|
||||||
|
set(CMAKE_C_EXTENSIONS OFF)
|
||||||
|
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||||
|
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||||
|
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
|
# Options
|
||||||
|
set(DEBUG OFF CACHE BOOL "Build MLX42 in debug mode, enabling assertions")
|
||||||
|
set(GLFW_FETCH ON CACHE BOOL "Clone and install GLFW")
|
||||||
|
set(BUILD_TESTS OFF CACHE BOOL "Build the tests to verify the integrity of the lib")
|
||||||
|
|
||||||
|
# Compile Options
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Reduce the size of LodePNG, we don't need these things.
|
||||||
|
add_definitions(-D LODEPNG_NO_COMPILE_ENCODER)
|
||||||
|
add_definitions(-D LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS)
|
||||||
|
|
||||||
|
if(UNIX)
|
||||||
|
set(CCSHADER ${PROJECT_SOURCE_DIR}/tools/compile_shader.sh)
|
||||||
|
add_compile_options(
|
||||||
|
-Wextra
|
||||||
|
-Wall
|
||||||
|
-Werror
|
||||||
|
-Wunreachable-code
|
||||||
|
|
||||||
|
# Some low priority warnings that are annoying.
|
||||||
|
-Wno-char-subscripts
|
||||||
|
-Wno-sign-compare
|
||||||
|
-Wno-unused-parameter
|
||||||
|
-Wno-missing-field-initializers
|
||||||
|
)
|
||||||
|
if(DEBUG)
|
||||||
|
message(STATUS "Building in DEBUG mode")
|
||||||
|
add_compile_options(-g)
|
||||||
|
else()
|
||||||
|
message(STATUS "Building in RELEASE mode")
|
||||||
|
add_definitions(-D NDEBUG)
|
||||||
|
add_compile_options(-Ofast)
|
||||||
|
endif(DEBUG)
|
||||||
|
else()
|
||||||
|
# TODO: Figure out what we need for windows.
|
||||||
|
set(CCSHADER ${PROJECT_SOURCE_DIR}/tools/compile_shader.bat)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Build specific files
|
||||||
|
# @see https://cmake.org/cmake/help/latest/command/add_custom_command.html
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
COMMENT "Building fragment shader"
|
||||||
|
DEPENDS ${PROJECT_SOURCE_DIR}/shaders/default.frag
|
||||||
|
OUTPUT mlx_frag_shader.c
|
||||||
|
COMMAND ${CCSHADER} ${PROJECT_SOURCE_DIR}/shaders/default.frag > mlx_frag_shader.c
|
||||||
|
VERBATIM
|
||||||
|
PRE_BUILD
|
||||||
|
USES_TERMINAL
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
COMMENT "Building vertex shader"
|
||||||
|
DEPENDS ${PROJECT_SOURCE_DIR}/shaders/default.vert
|
||||||
|
OUTPUT mlx_vert_shader.c
|
||||||
|
COMMAND ${CCSHADER} ${PROJECT_SOURCE_DIR}/shaders/default.vert > mlx_vert_shader.c
|
||||||
|
VERBATIM
|
||||||
|
PRE_BUILD
|
||||||
|
USES_TERMINAL
|
||||||
|
)
|
||||||
|
|
||||||
|
# Sources
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
add_library(mlx42 STATIC
|
||||||
|
|
||||||
|
# Root
|
||||||
|
${SOURCE_DIR}/mlx_cursor.c
|
||||||
|
${SOURCE_DIR}/mlx_exit.c
|
||||||
|
${SOURCE_DIR}/mlx_images.c
|
||||||
|
${SOURCE_DIR}/mlx_init.c
|
||||||
|
${SOURCE_DIR}/mlx_keys.c
|
||||||
|
${SOURCE_DIR}/mlx_loop.c
|
||||||
|
${SOURCE_DIR}/mlx_monitor.c
|
||||||
|
${SOURCE_DIR}/mlx_mouse.c
|
||||||
|
${SOURCE_DIR}/mlx_put_pixel.c
|
||||||
|
${SOURCE_DIR}/mlx_window.c
|
||||||
|
|
||||||
|
# Utils
|
||||||
|
${SOURCE_DIR}/utils/mlx_error.c
|
||||||
|
${SOURCE_DIR}/utils/mlx_list.c
|
||||||
|
${SOURCE_DIR}/utils/mlx_utils.c
|
||||||
|
${SOURCE_DIR}/utils/mlx_compare.c
|
||||||
|
|
||||||
|
# Textures
|
||||||
|
${SOURCE_DIR}/font/mlx_font.c
|
||||||
|
${SOURCE_DIR}/textures/mlx_png.c
|
||||||
|
${SOURCE_DIR}/textures/mlx_texture.c
|
||||||
|
${SOURCE_DIR}/textures/mlx_xpm42.c
|
||||||
|
|
||||||
|
# Libs
|
||||||
|
lib/png/lodepng.c
|
||||||
|
lib/glad/glad.c
|
||||||
|
|
||||||
|
mlx_vert_shader.c
|
||||||
|
mlx_frag_shader.c
|
||||||
|
)
|
||||||
|
target_include_directories(mlx42 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
|
# Dependencies
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
find_package(glfw3)
|
||||||
|
find_package(OpenGL REQUIRED)
|
||||||
|
|
||||||
|
target_link_libraries(mlx42 OpenGL::GL)
|
||||||
|
if (NOT glfw3_FOUND AND GLFW_FETCH)
|
||||||
|
message(STATUS "Install GLFW to supress this message")
|
||||||
|
message(STATUS "Please wait, fetching GLFW ...")
|
||||||
|
include(${CMAKE_DIR}/LinkGLFW.cmake)
|
||||||
|
LinkGLFW(mlx42)
|
||||||
|
elseif(NOT glfw3_FOUND AND NOT GLFW_FETCH)
|
||||||
|
message(FATAL_ERROR "Unable to build: GLFW can't be found nor fetched.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (glfw3_FOUND)
|
||||||
|
target_link_libraries(mlx42 ${GLFW3_LIBRARY})
|
||||||
|
endif()
|
||||||
|
if(APPLE)
|
||||||
|
target_link_libraries(mlx42 "-framework Cocoa" "-framework IOKit")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Testing
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Only build tests if we are the main project or explicitly told to this make sure
|
||||||
|
# tests are not built when mlx42 included as a subproject, use MLX42_BUILD_TESTS to overwrite this
|
||||||
|
# use cmake -DBUILD_TESTS=ON/-DMLX42_BUILD_TESTS=ON to build tests
|
||||||
|
|
||||||
|
if ((PROJECT_NAME STREQUAL CMAKE_PROJECT_NAME AND BUILD_TESTS) OR MLX42_BUILD_TESTS)
|
||||||
|
add_subdirectory(tests)
|
||||||
|
enable_testing()
|
||||||
|
endif()
|
116
MLX42/CODE_OF_CONDUCT.md
Normal file
116
MLX42/CODE_OF_CONDUCT.md
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
We as members, contributors, and leaders pledge to make participation in our
|
||||||
|
community a harassment-free experience for everyone, regardless of age, body
|
||||||
|
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||||
|
identity and expression, level of experience, education, socio-economic status,
|
||||||
|
nationality, personal appearance, race, religion or sexual identity
|
||||||
|
and orientation.
|
||||||
|
|
||||||
|
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||||
|
diverse, inclusive and healthy community.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to a positive environment for our
|
||||||
|
community include:
|
||||||
|
|
||||||
|
* Demonstrating empathy and kindness towards other people
|
||||||
|
* Being respectful of differing opinions, viewpoints and experiences
|
||||||
|
* Giving and gracefully accepting constructive feedback
|
||||||
|
* Accepting responsibility and apologizing to those affected by our mistakes
|
||||||
|
and learning from the experience
|
||||||
|
* Focusing on what is best not just for us as individuals, but for the
|
||||||
|
overall community
|
||||||
|
|
||||||
|
Examples of unacceptable behavior include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery and sexual attention or
|
||||||
|
advances of any kind
|
||||||
|
* Trolling, insulting or derogatory comments and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or email
|
||||||
|
address, without their explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a
|
||||||
|
professional setting
|
||||||
|
|
||||||
|
## Enforcement Responsibilities
|
||||||
|
|
||||||
|
Community leaders are responsible for clarifying and enforcing our standards of
|
||||||
|
acceptable behavior and will take appropriate and fair corrective action in
|
||||||
|
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||||
|
or harmful.
|
||||||
|
|
||||||
|
Community leaders have the right and responsibility to remove, edit or reject
|
||||||
|
comments, commits, code, wiki edits, issues and other contributions that are
|
||||||
|
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||||
|
decisions when appropriate.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies within all community spaces and also applies when
|
||||||
|
an individual is officially representing the community in public spaces.
|
||||||
|
Examples of representing our community include using an official e-mail address,
|
||||||
|
posting via an official social media account or acting as an appointed
|
||||||
|
representative at an online or offline event.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing or otherwise unacceptable behavior may be
|
||||||
|
reported to the community leaders responsible for enforcement at
|
||||||
|
main@w2wizard.dev.
|
||||||
|
All complaints will be reviewed and investigated promptly and fairly.
|
||||||
|
|
||||||
|
All community leaders are obligated to respect the privacy and security of the
|
||||||
|
reporter of any incident.
|
||||||
|
|
||||||
|
## Enforcement Guidelines
|
||||||
|
|
||||||
|
Community leaders will follow these Community Impact Guidelines in determining
|
||||||
|
the consequences for any action they deem in violation of this Code of Conduct:
|
||||||
|
|
||||||
|
### 1. Warning
|
||||||
|
|
||||||
|
**Community Impact**: A violation through a single incident or series
|
||||||
|
of actions.
|
||||||
|
|
||||||
|
**Consequence**: A warning with consequences for continued behavior. No
|
||||||
|
interaction with the people involved, including unsolicited interaction with
|
||||||
|
those enforcing the Code of Conduct, for a specified period of time. This
|
||||||
|
includes avoiding interactions in community spaces as well as external channels
|
||||||
|
like social media. Violating these terms may lead to a temporary or
|
||||||
|
permanent ban.
|
||||||
|
|
||||||
|
### 2. Temporary Ban
|
||||||
|
|
||||||
|
**Community Impact**: A serious violation of community standards, including
|
||||||
|
sustained inappropriate behavior.
|
||||||
|
|
||||||
|
**Consequence**: A temporary ban from any sort of interaction or public
|
||||||
|
communication with the community for a specified period of time. No public or
|
||||||
|
private interaction with the people involved, including unsolicited interaction
|
||||||
|
with those enforcing the Code of Conduct, is allowed during this period.
|
||||||
|
Violating these terms may lead to a permanent ban.
|
||||||
|
|
||||||
|
### 3. Permanent Ban
|
||||||
|
|
||||||
|
**Community Impact**: Demonstrating a pattern of violation of community
|
||||||
|
standards, including sustained inappropriate behavior, harassment of an
|
||||||
|
individual or aggression towards or disparagement of classes of individuals.
|
||||||
|
|
||||||
|
**Consequence**: A permanent ban from any sort of public interaction within
|
||||||
|
the community.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||||
|
version 2.0, available at
|
||||||
|
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||||
|
|
||||||
|
[homepage]: https://www.contributor-covenant.org
|
||||||
|
|
||||||
|
For answers to common questions about this code of conduct, see the FAQ at
|
||||||
|
https://www.contributor-covenant.org/faq. Translations are available at
|
||||||
|
https://www.contributor-covenant.org/translations.
|
20
MLX42/CONTRIBUTING.md
Normal file
20
MLX42/CONTRIBUTING.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# How to contribute to MLX42
|
||||||
|
|
||||||
|
## Read the wiki for repo codestyle!
|
||||||
|
|
||||||
|
For any questions, suggestions or help [Contact Me](mailto:lde-la-h@student.codam.nl)
|
||||||
|
|
||||||
|
## **Found a bug?**
|
||||||
|
|
||||||
|
* Avoid opening any new issues without having checked if your problem has already been reported. If there are no currently open issues that fit your problem's description, feel free to [add it](https://github.com/W2Codam/MLX42/issues/new/choose).
|
||||||
|
|
||||||
|
* When writing an issue make sure to include a clear title and description as well as having filled out all the necessary information: System info, OS, OS-Version, ...
|
||||||
|
|
||||||
|
* If possible add pictures of the issue.
|
||||||
|
|
||||||
|
* Maybe fix it yourself :D ?
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Before thinking of adding a contribution, think. Is it necessary? Will this actually be a useful/required feature? Is your implementation good?
|
||||||
|
Provide clear and documented explanation as to what was changed.
|
339
MLX42/LICENSE
Normal file
339
MLX42/LICENSE
Normal file
@ -0,0 +1,339 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Lesser General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License.
|
319
MLX42/README.md
Normal file
319
MLX42/README.md
Normal file
@ -0,0 +1,319 @@
|
|||||||
|
</br>
|
||||||
|
<div align="center">
|
||||||
|
<img src="https://user-images.githubusercontent.com/63303990/150698103-7e908ff3-abf8-4b0f-ad54-07a76b6c45e2.png" alt="42MLX_Logo">
|
||||||
|
</div>
|
||||||
|
<div align="center">
|
||||||
|
<sub>Written by <a href="https://portfolio.w2wizard.dev/">W2.Wizard</a> for the 42 Network</sub>
|
||||||
|
<div align="center">
|
||||||
|
</br>
|
||||||
|
<img src="https://img.shields.io/github/license/codam-coding-college/MLX42" alt="License GPL2.0">
|
||||||
|
<img src="https://svgshare.com/i/Zhy.svg" alt="Linux">
|
||||||
|
<img src="https://svgshare.com/i/ZjP.svg" alt="MacOS">
|
||||||
|
<img src="https://svgshare.com/i/ZhY.sv" alt="Windows">
|
||||||
|
<img src="https://github.com/codam-coding-college/MLX42/actions/workflows/ci.yml/badge.svg" alt="Build">
|
||||||
|
<img src="https://img.shields.io/github/forks/codam-coding-college/MLX42" alt="Forks">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
MLX42 is a performant, easy to use, cross-platform, minimal windowing graphics library to create graphical applications without having to work directly with the native windowing framework of the given operating system.
|
||||||
|
|
||||||
|
It provides primitive tools to draw textures onto the window as well as modifying them at runtime as they get displayed on the window.
|
||||||
|
|
||||||
|
# Features ✨
|
||||||
|
|
||||||
|
MLX42 comes with a plethora of features that make using it actually a joy instead of a chore.
|
||||||
|
|
||||||
|
## Cross-Platform 🖥️
|
||||||
|
|
||||||
|
Run it on your grandma's WindowsXP, on your uncle's debian or on a hipster's MacOS!
|
||||||
|
No matter what the platform, if MLX42 can build on it, it will run on its native windowing system.
|
||||||
|
|
||||||
|
This allows you to work on your project no matter which machine it is on.
|
||||||
|
|
||||||
|
## Documented 📚
|
||||||
|
|
||||||
|
MLX42 cares about good documentation, every function, usage and even some internal workings are documented!
|
||||||
|
No more guessing and searching how something functions or is supposed to work.
|
||||||
|
|
||||||
|
## Performance 🚀
|
||||||
|
|
||||||
|
It is built on OpenGL and uses batched rendering to speed up the rendering process compared to other libraries.
|
||||||
|
|
||||||
|
## Open source && Community driven 🌐
|
||||||
|
This project is being actively maintained by Codam as well as students from the 42 Network. This gives students the direct opportunity to learn more about the library itself as well as fix any potential bugs instead of merely accepting them.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Installation 🏗️
|
||||||
|
### General compilation.
|
||||||
|
|
||||||
|
Overall the building of this project is as follows for ALL systems. As long as CMake can make sense of it.
|
||||||
|
|
||||||
|
1. [Download and build MLX42](#download-and-build---mlx42)
|
||||||
|
|
||||||
|
In case your system doesn't have [glfw](https://github.com/glfw/glfw) installed cmake will detect this and download it for you.
|
||||||
|
You can then run `sudo make install` in the `_deps` directory of glfw. If you're using a 42 Computer (MacOS, Linux), ask your favourite sysadmin to install it.
|
||||||
|
Same goes for CMake or any other dependencies you might need for your system.
|
||||||
|
|
||||||
|
However if you can't do either CMake will still be able to fetch GLFW and build it. You can then statically link it from the `_deps` folder.
|
||||||
|
|
||||||
|
> **Note**: For Codam, GLFW is already installed on the Macs.
|
||||||
|
|
||||||
|
> **Note**: During the linking stage, the flag to link GLFW can either be: -lglfw3 or -lglfw depending on your system.
|
||||||
|
|
||||||
|
2. Compile your program with the library:
|
||||||
|
- For: [MacOS](#for-macos)
|
||||||
|
- For: [Linux](#for-linux)
|
||||||
|
- For: [Windows](#for-windows)
|
||||||
|
|
||||||
|
3. Profit!
|
||||||
|
|
||||||
|
### Unit tests
|
||||||
|
MLX42 comes with some unit tests to ensure the integrity of the library, to build them run the following command:
|
||||||
|
```sh
|
||||||
|
cmake -DBUILD_TESTS=ON -B build && cmake --build build --parallel
|
||||||
|
```
|
||||||
|
|
||||||
|
Then simply run them with:
|
||||||
|
```sh
|
||||||
|
ctest --output-on-failure --test-dir build
|
||||||
|
```
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## Download and build - MLX42
|
||||||
|
|
||||||
|
```bash
|
||||||
|
➜ ~ git clone https://github.com/codam-coding-college/MLX42.git
|
||||||
|
➜ ~ cd MLX42
|
||||||
|
➜ ~ cmake -B build # build here refers to the outputfolder.
|
||||||
|
➜ ~ cmake --build build -j4 # or do make -C build -j4
|
||||||
|
```
|
||||||
|
|
||||||
|
The output library file is called `libmlx42.a` and is located in the `build` folder that you specified.
|
||||||
|
|
||||||
|
### Available Options
|
||||||
|
|
||||||
|
You can pass build [options](./docs/index.md#available-options) to cmake, e.g: `cmake -DDEBUG=1 -DGLFW_FETCH=0...`. These will for instance let you build it in DEBUG mode or alter any sort of behaviour at build-time.
|
||||||
|
|
||||||
|
You can find an example makefile in the documentation [here](https://github.com/codam-coding-college/MLX42/blob/master/docs/Basics.md).
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## For MacOS:
|
||||||
|
|
||||||
|
### Installing the dependencies
|
||||||
|
|
||||||
|
If your system has neither GLFW nor CMake its highly recommended you use brew to install those missing dependencies.
|
||||||
|
|
||||||
|
For 42 Campuses you can use: [42Homebrew](https://github.com/kube/42homebrew)
|
||||||
|
```bash
|
||||||
|
# This will also install CMake.
|
||||||
|
# Be aware that this may take a while so be patient.
|
||||||
|
➜ ~ brew install glfw
|
||||||
|
```
|
||||||
|
|
||||||
|
For MacOS you need to use the following flags to compile your program with the library
|
||||||
|
in order to link the program with the correct frameworks:
|
||||||
|
```bash
|
||||||
|
-framework Cocoa -framework OpenGL -framework IOKit
|
||||||
|
```
|
||||||
|
|
||||||
|
Normally if you simply installed / built `glfw` from source or already have it installed
|
||||||
|
the compilation should be:
|
||||||
|
```bash
|
||||||
|
➜ ~ gcc main.c ... libmlx42.a -Iinclude -lglfw
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Via [Homebrew](https://brew.sh/) / [42Homebrew](https://github.com/kube/42homebrew)
|
||||||
|
```bash
|
||||||
|
# Homebrew
|
||||||
|
➜ ~ gcc main.c ... libmlx42.a -Iinclude -lglfw -L"/opt/homebrew/Cellar/glfw/3.3.8/lib/"
|
||||||
|
|
||||||
|
# 42Homebrew
|
||||||
|
➜ ~ gcc main.c ... libmlx42.a -Iinclude -lglfw -L"/Users/$USER/.brew/opt/glfw/lib/"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### MacOS Security:
|
||||||
|
|
||||||
|
When running your program in MacOS it may complain, because with Macs you just gotta think differently.
|
||||||
|
In case of any security warnings or MacOS telling you it can't verify the author/developer, go to ```Settings > Security & Privacy```.
|
||||||
|
|
||||||
|
There will be a pop-up at the bottom telling you that an application tried to run, click the option to let it run.
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## For Linux:
|
||||||
|
|
||||||
|
1. Install the necessary packages:
|
||||||
|
|
||||||
|
For Debian like (Ubuntu, Mint, Pop OS...):
|
||||||
|
```bash
|
||||||
|
➜ ~ sudo apt update
|
||||||
|
➜ ~ sudo apt install build-essential libx11-dev libglfw3-dev libglfw3 xorg-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
For Arch-linux (Manjaro, Endeavor, Garuda):
|
||||||
|
```bash
|
||||||
|
➜ ~ sudo pacman -S glfw-x11
|
||||||
|
```
|
||||||
|
OR (if you use sway/wlroots compositor or other wayland compositor)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
➜ ~ sudo pacman -S glfw-wayland
|
||||||
|
```
|
||||||
|
|
||||||
|
2. [Download and build MLX42](#download-and-build---mlx42)
|
||||||
|
|
||||||
|
3. Compile your program with the library:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
➜ ~ gcc main.c ... libmlx42.a -Iinclude -ldl -lglfw -pthread -lm
|
||||||
|
```
|
||||||
|
4. Profit!
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## For Windows (with Windows Subsystem for Linux 2 (WSL2))
|
||||||
|
|
||||||
|
1. Set these variables in your `.zshrc` or `.bashrc`:
|
||||||
|
```bash
|
||||||
|
export DISPLAY=$(ip route list default | awk '{print $3}'):0
|
||||||
|
export LIBGL_ALWAYS_INDIRECT=0
|
||||||
|
```
|
||||||
|
(If the DISPLAY export command is failing, see this [StackOverflow](https://stackoverflow.com/a/61110604) post for alternatives)
|
||||||
|
|
||||||
|
2. Download and install an XServer application with extended configuration (XMing does not qualify)
|
||||||
|
VcXsrv works: https://sourceforge.net/projects/vcxsrv/
|
||||||
|
|
||||||
|
3. Open Windows Defender Firewall, and follow these steps:
|
||||||
|
- Go to 'Allow an app or feature through Windows Defender Firewall'
|
||||||
|
- Change Settings
|
||||||
|
- Find the installed XServer, for VcXsrv that's 'VcXsrv windows server'
|
||||||
|
- Enable communication over Private **and** Public network
|
||||||
|
Optionally you might be able to provide these settings on first launch of the XServer application,
|
||||||
|
and they might not even show up in the list until the first time you start the app.
|
||||||
|
|
||||||
|
4. Start the XLaunch application (for VcXsrv) and provide these configuration settings:
|
||||||
|
- Leave Display number on auto
|
||||||
|
- Start no client
|
||||||
|
- **UNTICK** `Native opengl` option
|
||||||
|
- **TICK** `Disable access control`
|
||||||
|
- Finish starting the server
|
||||||
|
|
||||||
|
5. Probably all the other steps for Linux apply, just clone, build and run.
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## For Windows Native:
|
||||||
|
|
||||||
|
> **Warning**: Be aware that Visual Studio (2022) is required for this. Developing on Windows can be somewhat frustrating.
|
||||||
|
|
||||||
|
We highly recommend you simply use [WSL2](#for-windows-with-windows-subsystem-for-linux-2-wsl2) to make this as painless as possible.
|
||||||
|
However if you insist on building for windows natively then all you need in terms of dependencies is:
|
||||||
|
|
||||||
|
- [CMake](https://cmake.org/download/)
|
||||||
|
- [GLFW](https://www.glfw.org/download.html)
|
||||||
|
|
||||||
|
Once you have all the dependencies correctly installed `CMake` will generate
|
||||||
|
the visual studio project files. Simply build it and once you have a `.lib` file
|
||||||
|
move them to your actual project and install them as you would with any other library.
|
||||||
|
|
||||||
|
Just in case here's a [video](https://youtu.be/or1dAmUO8k0?t=494) showing you how this can be done. Conveniently this video also covers how you can link `glfw`.
|
||||||
|
|
||||||
|
Of course it's up to you to make sure that the code you write is portable. Things that exist on `Unix` don't necessarily exist on `Win32`.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
![MLX42](docs/assets/demo.gif)
|
||||||
|
|
||||||
|
```c
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Codam Coding College, Amsterdam @ 2022-2023 by W2Wizard.
|
||||||
|
// See README in the root project for more information.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <MLX42/MLX42.h>
|
||||||
|
|
||||||
|
#define WIDTH 512
|
||||||
|
#define HEIGHT 512
|
||||||
|
|
||||||
|
static mlx_image_t* image;
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int32_t ft_pixel(int32_t r, int32_t g, int32_t b, int32_t a)
|
||||||
|
{
|
||||||
|
return (r << 24 | g << 16 | b << 8 | a);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ft_randomize(void* param)
|
||||||
|
{
|
||||||
|
for (int32_t i = 0; i < image->width; ++i)
|
||||||
|
{
|
||||||
|
for (int32_t y = 0; y < image->height; ++y)
|
||||||
|
{
|
||||||
|
uint32_t color = ft_pixel(
|
||||||
|
rand() % 0xFF, // R
|
||||||
|
rand() % 0xFF, // G
|
||||||
|
rand() % 0xFF, // B
|
||||||
|
rand() % 0xFF // A
|
||||||
|
);
|
||||||
|
mlx_put_pixel(image, i, y, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ft_hook(void* param)
|
||||||
|
{
|
||||||
|
mlx_t* mlx = param;
|
||||||
|
|
||||||
|
if (mlx_is_key_down(mlx, MLX_KEY_ESCAPE))
|
||||||
|
mlx_close_window(mlx);
|
||||||
|
if (mlx_is_key_down(mlx, MLX_KEY_UP))
|
||||||
|
image->instances[0].y -= 5;
|
||||||
|
if (mlx_is_key_down(mlx, MLX_KEY_DOWN))
|
||||||
|
image->instances[0].y += 5;
|
||||||
|
if (mlx_is_key_down(mlx, MLX_KEY_LEFT))
|
||||||
|
image->instances[0].x -= 5;
|
||||||
|
if (mlx_is_key_down(mlx, MLX_KEY_RIGHT))
|
||||||
|
image->instances[0].x += 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int32_t main(int32_t argc, const char* argv[])
|
||||||
|
{
|
||||||
|
mlx_t* mlx;
|
||||||
|
|
||||||
|
// Gotta error check this stuff
|
||||||
|
if (!(mlx = mlx_init(WIDTH, HEIGHT, "MLX42", true)))
|
||||||
|
{
|
||||||
|
puts(mlx_strerror(mlx_errno));
|
||||||
|
return(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (!(image = mlx_new_image(mlx, 128, 128)))
|
||||||
|
{
|
||||||
|
mlx_close_window(mlx);
|
||||||
|
puts(mlx_strerror(mlx_errno));
|
||||||
|
return(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (mlx_image_to_window(mlx, image, 0, 0) == -1)
|
||||||
|
{
|
||||||
|
mlx_close_window(mlx);
|
||||||
|
puts(mlx_strerror(mlx_errno));
|
||||||
|
return(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
mlx_loop_hook(mlx, ft_randomize, mlx);
|
||||||
|
mlx_loop_hook(mlx, ft_hook, mlx);
|
||||||
|
|
||||||
|
mlx_loop(mlx);
|
||||||
|
mlx_terminate(mlx);
|
||||||
|
return (EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
13
MLX42/SECURITY.md
Normal file
13
MLX42/SECURITY.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
|
||||||
|
| Version | Supported |
|
||||||
|
| ------- | ------------------ |
|
||||||
|
| 2.x.x | ✅ |
|
||||||
|
| 1.0.x | ❌ |
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
For security issues please refrain from opening an issue!
|
||||||
|
Instead write an email to [main@w2wizard.dev](mailto:main@w2wizard.dev)
|
43
MLX42/cmake/Findglfw3.cmake
Normal file
43
MLX42/cmake/Findglfw3.cmake
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Codam Coding College, Amsterdam @ 2022-2023 by W2Wizard.
|
||||||
|
# See README in the root project for more information.
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Try to find GLFW3 library and include path.
|
||||||
|
# Once done this will define:
|
||||||
|
# - GLFW3_FOUND
|
||||||
|
# - GLFW3_INCLUDE_PATH
|
||||||
|
# - GLFW3_LIBRARY
|
||||||
|
|
||||||
|
# Possbile header locations
|
||||||
|
set(_glfw3_HEADER_SEARCH_DIRS
|
||||||
|
"/usr/include"
|
||||||
|
"/usr/local/include"
|
||||||
|
"C:/Program Files/GLFW/include"
|
||||||
|
"C:/Program Files (x86)/GLFW/include"
|
||||||
|
"$ENV{HOME}/.brew/include/"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Possbile library locations
|
||||||
|
set(_glfw3_LIB_SEARCH_DIRS
|
||||||
|
"/usr/lib"
|
||||||
|
"/usr/local/lib"
|
||||||
|
"C:/Program Files/GLFW"
|
||||||
|
"C:/Program Files (x86)/GLFW"
|
||||||
|
"$ENV{HOME}/.brew/lib/"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Search for the header
|
||||||
|
find_path(GLFW3_INCLUDE_PATH "GLFW/glfw3.h" PATHS ${_glfw3_HEADER_SEARCH_DIRS})
|
||||||
|
|
||||||
|
# Search for the library
|
||||||
|
find_library(GLFW3_LIBRARY NAMES glfw3 glfw PATHS ${_glfw3_LIB_SEARCH_DIRS})
|
||||||
|
|
||||||
|
if (GLFW3_INCLUDE_PATH AND GLFW3_LIBRARY)
|
||||||
|
set(glfw3_FOUND "YES")
|
||||||
|
include_directories(${GLFW3_INCLUDE_PATH})
|
||||||
|
message(STATUS "Found GLFW: ${GLFW3_LIBRARY}")
|
||||||
|
else()
|
||||||
|
set(glfw3_FOUND "NO")
|
||||||
|
message(WARNING "Unable to find dependency: GLFW\nDid you install it?")
|
||||||
|
endif()
|
38
MLX42/cmake/LinkGLFW.cmake
Normal file
38
MLX42/cmake/LinkGLFW.cmake
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Codam Coding College, Amsterdam @ 2022-2023 by W2Wizard.
|
||||||
|
# See README in the root project for more information.
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
include(FetchContent)
|
||||||
|
|
||||||
|
macro(LinkGLFW TARGET)
|
||||||
|
FetchContent_Declare(
|
||||||
|
glfw
|
||||||
|
GIT_REPOSITORY https://github.com/glfw/glfw
|
||||||
|
GIT_TAG 3.3.8
|
||||||
|
)
|
||||||
|
|
||||||
|
FetchContent_GetProperties(glfw)
|
||||||
|
|
||||||
|
if (NOT glfw_POPULATED)
|
||||||
|
FetchContent_Populate(glfw)
|
||||||
|
|
||||||
|
# Just configure GLFW only
|
||||||
|
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "Build Examples" FORCE)
|
||||||
|
set(GLFW_BUILD_TESTS OFF CACHE BOOL "Build tests" FORCE)
|
||||||
|
set(GLFW_BUILD_DOCS OFF CACHE BOOL "Build docs" FORCE)
|
||||||
|
set(GLFW_INSTALL ON CACHE BOOL "Configure an install" FORCE)
|
||||||
|
|
||||||
|
# This excludes glfw from being rebuilt when ALL_BUILD is built
|
||||||
|
# it will only be built when a target is built that has a dependency on glfw
|
||||||
|
add_subdirectory(${glfw_SOURCE_DIR} ${glfw_BINARY_DIR} EXCLUDE_FROM_ALL)
|
||||||
|
|
||||||
|
# Set the target's folders
|
||||||
|
set_target_properties(glfw PROPERTIES FOLDER ${PROJECT_NAME}/thirdparty)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_include_directories(${TARGET} PRIVATE ${glfw_SOURCE_DIR}/include)
|
||||||
|
target_link_libraries(${TARGET} glfw)
|
||||||
|
|
||||||
|
add_dependencies(${TARGET} glfw)
|
||||||
|
endmacro()
|
181
MLX42/docs/42.md
Normal file
181
MLX42/docs/42.md
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
<!----------------------------------------------------------------------------
|
||||||
|
Copyright @ 2021-2022 Codam Coding College. All rights reserved.
|
||||||
|
See copyright and license notice in the root project for more information.
|
||||||
|
----------------------------------------------------------------------------->
|
||||||
|
|
||||||
|
</br>
|
||||||
|
<div align="center">
|
||||||
|
<img src="./assets/logo.png" alt="42MLX_Logo">
|
||||||
|
</div>
|
||||||
|
<div align="center" style="margin-top: 8px;">
|
||||||
|
<sub>Written by <a href="https://portfolio.w2wizard.dev/">W2.Wizard</a> for the 42 Network</sub>
|
||||||
|
</div>
|
||||||
|
</br>
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<h1>Welcome to the MLX42, 42Campus documentation</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
# Foreword
|
||||||
|
If you're considering allowing the use of MLX42 in your campus and wondering why you should do it, how it should work, and what it will take to get it working, then you're in the right place!
|
||||||
|
|
||||||
|
MLX42 has been battle-tested multiple times at hackathons and other campuses and has received over 500 commits since 2021. All students share the same sentiment: they enjoy using the library, but it's not too easy to finish the projects. During that time many bugs, leaks, and segfaults have been fixed.
|
||||||
|
|
||||||
|
It addresses one of the main problems at 42, which is that although it is a tech school, it does not provide its students with well-maintained tools to improve their education. All a campus wants is to give its students the best they can.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Technical comparison
|
||||||
|
## MiniLibX
|
||||||
|
The miniLibX has many problems that have been around for almost 10+ years:
|
||||||
|
|
||||||
|
- `Not maintained`: The library is practically dead, and it's unclear who is available to fix the bugs. It hasn't had any changes in a long time, and student pull requests on Github for the X11 version go unnoticed. Issues are also being ignored.
|
||||||
|
|
||||||
|
- `Poor documentation`: The documentation consists of a few man pages that are outdated and an online documentation created by another student. It's understandable that students have to learn on their own, but a library with an extensive API requires proper documentation for anyone to start understanding it.
|
||||||
|
|
||||||
|
- `Poor execution`: There are multiple versions: OpenGL, Swift, and X11. Instead of becoming better with each new iteration, they stay the same with no real improvement. It should be future-proof and not dependent on a specific platform. People are struggling with the there being so many different versions that they start loosing track where the problem actually is.
|
||||||
|
|
||||||
|
- `Not cross-platform`: Students constantly encounter the same problem: at school they work with MacOS, but at home they use Linux. Or they write their project on Linux, but want to show it to their parents using Windows or MacOS. At each point, miniLibX fails to fill that gap. The pandemic in 2019 showed just how much students struggled to evaluate each other using different machines and versions.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## MLX42
|
||||||
|
|
||||||
|
The main goal of MLX42 is to address all of these shortcomings of the original versions. There are some differences, mainly in the way images are rendered, but everything else is basically the same.
|
||||||
|
|
||||||
|
So far, all of the drawbacks of miniLibX have been taken care of, and students using it are enjoying it!
|
||||||
|
|
||||||
|
### Rendering
|
||||||
|
|
||||||
|
One of the biggest differences between the two libraries is the way rendering is handled.
|
||||||
|
|
||||||
|
In `miniLibX`, students change the buffer of an image and then push it to the window.
|
||||||
|
In `MLX42`, students put the image to the window and can change the buffer at any time, resulting in an immediate update to the image.
|
||||||
|
|
||||||
|
MLX42 uses instances instead. An image is like the original painting, while instances are individual copies of this painting on the window.
|
||||||
|
|
||||||
|
There is no window clearing function because students need to learn how to properly manage their images. They can still delete images and turn instances on or off, of course.
|
||||||
|
|
||||||
|
Internally, it uses batched rendering to further improve performance. The actual documentation and the code itself have more details.
|
||||||
|
|
||||||
|
### Maintained & Open-source
|
||||||
|
|
||||||
|
The main goal of MLX42 is to empower students and pedagogues by giving them the ability to maintain and fix bugs, instead of leaving their complaints unaddressed. By being open-source, students can explore the code and submit pull requests.
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
The repository comes with a well-maintained [Wiki](https://github.com/codam-coding-college/MLX42/wiki) and documentation in the form of `markdown` files in the repository root.
|
||||||
|
|
||||||
|
### Build system
|
||||||
|
|
||||||
|
MLX42 initially used `make`, but it was inflexible and caused weird bugs for others. Since version 2.3.0 it uses `cmake` for a truly cross-platform build system.
|
||||||
|
|
||||||
|
Students do not need to understand how to use `cmake`, as building the library requires only two shell commands. The instructions on how to build the library are provided to them.
|
||||||
|
|
||||||
|
### XPM42
|
||||||
|
For historical reasons, I included my own file format that mimics XPM3. In the original miniLibX, the way XPM files were handled made no sense, as they were supposed to be compiled into the binary. Instead, miniLibX parsed the files and pasted the data into memory.
|
||||||
|
|
||||||
|
In the `tools` folder, there is a python script that converts XPM3 to XPM42. XPM42 is available as an alternative, but it is highly encouraged to use the PNG importer, which does not leak and uses lodepng for parsing.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### How can I migrate? What is necessary to change?
|
||||||
|
|
||||||
|
Migrating to MLX42 is easy and requires minimal effort, it requires just 2 dependencies in order to work.
|
||||||
|
|
||||||
|
#### Dependencies
|
||||||
|
- [CMake: >= 3.18.0](https://cmake.org/download/)
|
||||||
|
- [GLFW: >= 3.3.6](https://github.com/glfw/glfw)
|
||||||
|
|
||||||
|
It is up to your pedago staff or system administrator to determine how to distribute MLX42 to students.
|
||||||
|
|
||||||
|
The options are:
|
||||||
|
|
||||||
|
- `A`: Install it on the machine in a location such as /usr/local/lib and use -lmlx42 to link it.
|
||||||
|
|
||||||
|
- `B`: Have students clone the repository, preferably as a submodule, and include it in their repository.
|
||||||
|
|
||||||
|
There is not much else to do besides these steps. It is a straightforward replacement, and the choice of distribution is up to the campus.
|
||||||
|
|
||||||
|
## F.A.Q
|
||||||
|
|
||||||
|
Q: **_"It has too many features! I think students should implement some of them themselves..."_**
|
||||||
|
|
||||||
|
A: I can agree that there may be some features that do too much for the students. However, this can be fixed simply by banning the usage of these functions or removing them from the library.
|
||||||
|
|
||||||
|
Either way, the majority of additional functions are just GLFW wrappers to enable more extensive customization of the window, such as cursors and executable icons. Students can ignore them, and for those who want them, they are available without impeding their learning.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Q: **_"The `mlx_put_pixel` works too well..."_**
|
||||||
|
|
||||||
|
A: Rather than purposefully sabotaging the library to make a point, I deemed it necessary that the library simply works. By default, this function is already banned by all subjects, and the main idea was to force students to use images.
|
||||||
|
|
||||||
|
In MLX42 it always starts with an image, and students are forced to face images no matter what. They still face the same learning curve of how to modify the buffer of an image and learn the concept of bit shifting one way or another.
|
||||||
|
|
||||||
|
Our proposal is to allow its use in the first three graphics projects (fract-ol, fdf, so_long) and later ban it for the remaining ones (Cub3D, MiniRT), so students can become familiar with it and then need to explore its workings.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Q: **_"Are the libraries 1:1 identical?"_**
|
||||||
|
|
||||||
|
A: No, there are 100% breaking changes, and changing from miniLibX to MLX42 will not be a simple drop-in replacement. As in their API is slightly different. That was not the idea eitherway, as it would be impossible to fix the problems present in the current miniLibX.
|
||||||
|
|
||||||
|
In terms of usage, it's practically identical, while the API Prototypes are slightly different, the usage is roughly the same and the only core difference is the way images are handled.
|
||||||
|
|
||||||
|
My suggestion is for students who are using miniLibX to keep using it to finish their project and for new students to prefer the new one or until they reach the next graphical project.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Q: **_"With regards to how the rendering is done, won't that make it too easy for students?"_**
|
||||||
|
|
||||||
|
A: After almost a year in use, both new students who didn't use the old one and students who used both managed just fine and even appreciated this change in the way rendering works in MLX42.
|
||||||
|
|
||||||
|
It is not taking away from the learning experience, it's just shifting a function call from one place to another. Students still find it challenging to finish the actual project, as they still need to learn a whole new library and how it operates.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Q: **_"OpenGL? Isn't that a bit old by now?"_**
|
||||||
|
|
||||||
|
A: Is OpenGL old? Sure. But in the end, students don't care. You could argue that it's less future-proof and that Vulkan should be used instead. But ask yourself, does one need an artillery cannon to hunt for a rabbit in a forest? If your answer is no, then why does one need Vulkan to render a bunch of quads on a window?
|
||||||
|
|
||||||
|
OpenGL is easy to learn, widely supported and it could be argued that it's actually useful for students who are interested in graphics. Anyway, if one day Vulkan is required, a branch and PR can be created and merged!
|
||||||
|
|
||||||
|
Just a small reminder that it takes roughly [700+ lines of code](https://github.com/SaschaWillems/Vulkan/blob/master/examples/triangle/triangle.cpp) to render a triangle with vulkan...
|
||||||
|
|
||||||
|
Here is the equivalent in [OpenGL](https://learnopengl.com/code_viewer_gh.php?code=src/1.getting_started/2.1.hello_triangle/hello_triangle.cpp).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Q: **_"CMake? Won't that confuse them?"_**
|
||||||
|
|
||||||
|
A: It is 2 simple commands that are described in the README, and it's a good opportunity to learn a new way to build your projects.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Q: **_"Who will maintain MLX42? How long can this be guaranteed?"_**
|
||||||
|
|
||||||
|
A: Currently it is being maintained by `lde-la-h` (W2Wizard). However commits from the 42 Pedago or really anyone are very much welcome.
|
||||||
|
I myself have been taking care of it since the 1st of January 2021 and aim to continue to support it until I can't.
|
||||||
|
|
||||||
|
Once the time comes, someone else will take the lead of maintaing the library whoever that may be.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Q: **_"Do we need to update translations or subjects, etc??"_**
|
||||||
|
|
||||||
|
A: Regarding the subjects, as long as the library not being adopted there's little room for change in this regard. However the good news is that it basically requires zero effort besides updating the links on the intra and maybe changing the name referenced inside the pdf's. There is really nothing necessary to change besides minor things and to adapt these changes would literally just require at most a day of effort.
|
||||||
|
|
||||||
|
If you're really unusure, you as a pedago / campus can just choose to adopt it and mention to students that they can git clone it from here.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Q: **_"What if we want to ban some functions?"_**
|
||||||
|
|
||||||
|
A: Contact the maintainer or make a PR with the suggestion and watch it get merged or rejected. All it requires is communication... Any change is welcome if it so desired. You don't have to accept anything as is, that is the point of all of this. That if something needs to change, it can actually happen.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Q: **_"I don't like the fact that it uses GLFW for the window..."_**
|
||||||
|
|
||||||
|
A: `¯\_(ツ)_/¯` Well it's better than using the native windowing framework, at least it is portable, at least if something is wrong with it students can actually fix it by making a PR to the respective repository. Additionally GLFW is pretty standard for things like this, simply checkout any graphics demo and somewhere you will end up with GLFW under the hood quite often.
|
||||||
|
|
137
MLX42/docs/Basics.md
Normal file
137
MLX42/docs/Basics.md
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
<!----------------------------------------------------------------------------
|
||||||
|
Copyright @ 2021-2022 Codam Coding College. All rights reserved.
|
||||||
|
See copyright and license notice in the root project for more information.
|
||||||
|
----------------------------------------------------------------------------->
|
||||||
|
|
||||||
|
# Basics
|
||||||
|
|
||||||
|
Before starting please read the [index page](./index.md).
|
||||||
|
Starting with MLX42 is very straightforward. Here we will make a simple program that will use a makefile and compile
|
||||||
|
MLX42.
|
||||||
|
|
||||||
|
## Makefile Example
|
||||||
|
|
||||||
|
If you're curious as to how to configure a makefile with MLX42 here is a Makefile example from a project.
|
||||||
|
Use this as a guide on how to compile MLX42 and use it in your application.
|
||||||
|
|
||||||
|
First of all we need a makefile that can compile our program, below you can see a sample makefile:
|
||||||
|
|
||||||
|
```makefile
|
||||||
|
NAME := Game
|
||||||
|
CFLAGS := -Wextra -Wall -Werror -Wunreachable-code -Ofast
|
||||||
|
LIBMLX := ./lib/MLX42
|
||||||
|
|
||||||
|
HEADERS := -I ./include -I $(LIBMLX)/include
|
||||||
|
LIBS := $(LIBMLX)/build/libmlx42.a -ldl -lglfw -pthread -lm
|
||||||
|
SRCS := $(shell find ./src -iname "*.c")
|
||||||
|
OBJS := ${SRCS:.c=.o}
|
||||||
|
|
||||||
|
all: libmlx $(NAME)
|
||||||
|
|
||||||
|
libmlx:
|
||||||
|
@cmake $(LIBMLX) -B $(LIBMLX)/build && make -C $(LIBMLX)/build -j4
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
@$(CC) $(CFLAGS) -o $@ -c $< $(HEADERS) && printf "Compiling: $(notdir $<)"
|
||||||
|
|
||||||
|
$(NAME): $(OBJS)
|
||||||
|
@$(CC) $(OBJS) $(LIBS) $(HEADERS) -o $(NAME)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@rm -f $(OBJS)
|
||||||
|
@rm -f $(LIBMLX)/build
|
||||||
|
|
||||||
|
fclean: clean
|
||||||
|
@rm -f $(NAME)
|
||||||
|
|
||||||
|
re: clean all
|
||||||
|
|
||||||
|
.PHONY: all, clean, fclean, re, libmlx
|
||||||
|
```
|
||||||
|
|
||||||
|
## Main
|
||||||
|
|
||||||
|
Below is a simple main into starting a window. MLX42 has several nice features that allow you to predefine how it should behave during runtime such as `MLX_HEADLESS` running it without opening a window or `MLX_STRETCH_IMAGE` which stretches the window content with the window size.
|
||||||
|
|
||||||
|
The exact structure `mlx_init()` is basically a handle that stores important information
|
||||||
|
regarding the window and looks as follows:
|
||||||
|
|
||||||
|
```c
|
||||||
|
/**
|
||||||
|
* Main MLX handle, carries important data in regards to the program.
|
||||||
|
* @param window The window itself.
|
||||||
|
* @param context Abstracted opengl data.
|
||||||
|
* @param width The width of the window.
|
||||||
|
* @param height The height of the window.
|
||||||
|
* @param delta_time The time difference between the previous frame and the current frame.
|
||||||
|
*/
|
||||||
|
typedef struct mlx
|
||||||
|
{
|
||||||
|
void* window;
|
||||||
|
void* context;
|
||||||
|
int32_t width;
|
||||||
|
int32_t height;
|
||||||
|
double delta_time;
|
||||||
|
} mlx_t;
|
||||||
|
```
|
||||||
|
|
||||||
|
Between initializations you can do everything that is required such as drawing your image or opening files.
|
||||||
|
Once `mlx_loop()` is reached the program remains open until a shutdown is somehow requested, e.g: closing the window.
|
||||||
|
|
||||||
|
Because we want programs to be interactive and do stuff it's very useful to hook into the looping process of `mlx_loop()`.
|
||||||
|
In order to achieve this we use [hooks](./Hooks.md).
|
||||||
|
|
||||||
|
`NOTE: Compile MLX42 with DEBUG=1 to see assertions and to add debug flags. This can help you find critical mistakes during development!`
|
||||||
|
|
||||||
|
```c
|
||||||
|
// Written by Bruh
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "MLX42/MLX42.h"
|
||||||
|
#define WIDTH 256
|
||||||
|
#define HEIGHT 256
|
||||||
|
|
||||||
|
// Exit the program as failure.
|
||||||
|
static void ft_error(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s", mlx_strerror(mlx_errno));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the window width and height.
|
||||||
|
static void ft_hook(void* param)
|
||||||
|
{
|
||||||
|
const mlx_t* mlx = param;
|
||||||
|
|
||||||
|
printf("WIDTH: %d | HEIGHT: %d\n", mlx->width, mlx->height);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t main(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
// MLX allows you to define its core behaviour before startup.
|
||||||
|
mlx_set_setting(MLX_MAXIMIZED, true);
|
||||||
|
mlx_t* mlx = mlx_init(WIDTH, HEIGHT, "42Balls", true);
|
||||||
|
if (!mlx)
|
||||||
|
ft_error();
|
||||||
|
|
||||||
|
/* Do stuff */
|
||||||
|
|
||||||
|
// Create and display the image.
|
||||||
|
mlx_image_t* img = mlx_new_image(mlx, 256, 256);
|
||||||
|
if (!img || (mlx_image_to_window(mlx, img, 0, 0) < 0))
|
||||||
|
ft_error();
|
||||||
|
|
||||||
|
// Even after the image is being displayed, we can still modify the buffer.
|
||||||
|
mlx_put_pixel(img, 0, 0, 0xFF0000FF);
|
||||||
|
|
||||||
|
// Register a hook and pass mlx as an optional param.
|
||||||
|
// NOTE: Do this before calling mlx_loop!
|
||||||
|
mlx_loop_hook(mlx, ft_hook, mlx);
|
||||||
|
mlx_loop(mlx);
|
||||||
|
mlx_terminate(mlx);
|
||||||
|
return (EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
```
|
100
MLX42/docs/Colors.md
Normal file
100
MLX42/docs/Colors.md
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
<!----------------------------------------------------------------------------
|
||||||
|
Copyright @ 2021-2022 Codam Coding College. All rights reserved.
|
||||||
|
See copyright and license notice in the root project for more information.
|
||||||
|
----------------------------------------------------------------------------->
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
Colors are a fundamental concept in graphics programming. A common color model is RGBA, which MLX uses for storing and displaying images.
|
||||||
|
|
||||||
|
## Composition
|
||||||
|
Colors are commonly represented as `4-byte` integers. This 4-byte integer is a grouping of four individual channels: red, green, blue and alpha, with alpha representing transparency. Additionally, colors are usually shown in hexadecimal to make each channel value identifiable:
|
||||||
|
|
||||||
|
Channel | Description | RGBA representation
|
||||||
|
:------:|:-------------:|:-------------------:
|
||||||
|
`R` | Red Channel | `0xFF000000`
|
||||||
|
`G` | Green Channel | `0x00FF0000`
|
||||||
|
`B` | Blue Channel | `0x0000FF00`
|
||||||
|
`A` | Alpha Channel | `0x000000FF`
|
||||||
|
|
||||||
|
Combining these four channel values into one will result in a non-transparent, white color.
|
||||||
|
|
||||||
|
## Encoding & Decoding
|
||||||
|
|
||||||
|
In order to set each channel's byte we can use bit-shifting operations.
|
||||||
|
|
||||||
|
A function that combines four individual channel bytes into a single integer using bit-shifting looks like this:
|
||||||
|
|
||||||
|
```c
|
||||||
|
// 'Encodes' four individual bytes into an int.
|
||||||
|
int get_rgba(int r, int g, int b, int a)
|
||||||
|
{
|
||||||
|
return (r << 24 | g << 16 | b << 8 | a);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
We can also do this in reverse to retrieve each individual byte again:
|
||||||
|
|
||||||
|
```c
|
||||||
|
// Get the red channel.
|
||||||
|
int get_r(int rgba)
|
||||||
|
{
|
||||||
|
// Move 3 bytes to the right and mask out the first byte.
|
||||||
|
return ((rgba >> 24) & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the green channel.
|
||||||
|
int get_g(int rgba)
|
||||||
|
{
|
||||||
|
// Move 2 bytes to the right and mask out the first byte.
|
||||||
|
return ((rgba >> 16) & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the blue channel.
|
||||||
|
int get_b(int rgba)
|
||||||
|
{
|
||||||
|
// Move 1 byte to the right and mask out the first byte.
|
||||||
|
return ((rgba >> 8) & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the alpha channel.
|
||||||
|
int get_a(int rgba)
|
||||||
|
{
|
||||||
|
// Move 0 bytes to the right and mask out the first byte.
|
||||||
|
return (rgba & 0xFF);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
In this small example we will create a white image:
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include "MLX42/MLX42.h"
|
||||||
|
|
||||||
|
// Bytes Per Pixel. Since each pixel is represented as an integer, it will be four bytes for four channels.
|
||||||
|
#define BPP sizeof(int32_t)
|
||||||
|
|
||||||
|
int32_t main(void)
|
||||||
|
{
|
||||||
|
// Init mlx with a canvas size of 256x256 and the ability to resize the window.
|
||||||
|
mlx_t* mlx = mlx_init(256, 256, "MLX42", true);
|
||||||
|
|
||||||
|
if (!mlx) exit(EXIT_FAILURE);
|
||||||
|
|
||||||
|
// Create a 128x128 image.
|
||||||
|
mlx_image_t* img = mlx_new_image(mlx, 128, 128);
|
||||||
|
|
||||||
|
// Set the channels of each pixel in our image to the maximum byte value of 255.
|
||||||
|
memset(img->pixels, 255, img->width * img->height * BPP);
|
||||||
|
|
||||||
|
// Draw the image at coordinate (0, 0).
|
||||||
|
mlx_image_to_window(mlx, img, 0, 0);
|
||||||
|
|
||||||
|
// Run the main loop and terminate on quit.
|
||||||
|
mlx_loop(mlx);
|
||||||
|
mlx_terminate(mlx);
|
||||||
|
|
||||||
|
return (EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
8
MLX42/docs/Functions.md
Normal file
8
MLX42/docs/Functions.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<!----------------------------------------------------------------------------
|
||||||
|
Copyright @ 2021-2022 Codam Coding College. All rights reserved.
|
||||||
|
See copyright and license notice in the root project for more information.
|
||||||
|
----------------------------------------------------------------------------->
|
||||||
|
|
||||||
|
# Functions
|
||||||
|
|
||||||
|
A list of all functions can be found here: [Functions](https://bit.ly/3aWZL7C)
|
229
MLX42/docs/Hooks.md
Normal file
229
MLX42/docs/Hooks.md
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
<!----------------------------------------------------------------------------
|
||||||
|
Copyright @ 2021-2022 Codam Coding College. All rights reserved.
|
||||||
|
See copyright and license notice in the root project for more information.
|
||||||
|
----------------------------------------------------------------------------->
|
||||||
|
|
||||||
|
# Hooks in MLX42
|
||||||
|
|
||||||
|
Hooks allow you to add your own functions to the main loop execution of the program, aka these functions get executed every frame.
|
||||||
|
They also serve to intercept certain keypresses such as scrolling or pressing enter.
|
||||||
|
|
||||||
|
Only one hook can be set at a time! You cannot attach/have multiple specialized hooks.
|
||||||
|
You can however have multiple generic hooks.
|
||||||
|
|
||||||
|
## Specialized Hooks
|
||||||
|
|
||||||
|
### Scroll hook
|
||||||
|
```c
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function used to handle scrolling.
|
||||||
|
*
|
||||||
|
* @param[in] x The mouse x delta.
|
||||||
|
* @param[in] y The mouse y delta.
|
||||||
|
* @param[in] param Additional parameter to pass to the function.
|
||||||
|
*/
|
||||||
|
typedef void (*mlx_scrollfunc)(double xdelta, double ydelta, void* param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function sets the scroll callback, which is called when a scrolling
|
||||||
|
* device is used, such as a mouse wheel.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] func The scroll wheel callback function.
|
||||||
|
* @param[in] param An additional optional parameter.
|
||||||
|
*/
|
||||||
|
void mlx_scroll_hook(mlx_t* mlx, mlx_scrollfunc func, void* param);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Close Hook
|
||||||
|
|
||||||
|
```c
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function used to handle window closing which is called when the user attempts
|
||||||
|
* to close the window, for example by clicking the close widget in the title bar.
|
||||||
|
*
|
||||||
|
* @param[in] param Additional parameter to pass to the function.
|
||||||
|
*/
|
||||||
|
typedef void (*mlx_closefunc)(void* param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function sets the close callback, which is called in attempt to close
|
||||||
|
* the window device such as a close window widget used in the window bar.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] func The close callback function.
|
||||||
|
* @param[in] param An additional optional parameter.
|
||||||
|
*/
|
||||||
|
void mlx_close_hook(mlx_t* mlx, mlx_closefunc func, void* param);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Resize Hook
|
||||||
|
|
||||||
|
```c
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function used to handle window resizing.
|
||||||
|
*
|
||||||
|
* @param[in] width The new width of the window.
|
||||||
|
* @param[in] height The new height of the window.
|
||||||
|
* @param[in] param Additional parameter to pass to the function.
|
||||||
|
*/
|
||||||
|
typedef void (*mlx_resizefunc)(int32_t width, int32_t height, void* param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function sets the resize callback, which is called when the window is
|
||||||
|
* resized
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] func The resize callback function.
|
||||||
|
* @param[in] param An additional optional parameter.
|
||||||
|
*/
|
||||||
|
void mlx_resize_hook(mlx_t* mlx, mlx_resizefunc func, void* param);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key hook
|
||||||
|
|
||||||
|
Use a key hook if you want single keypress detection or more precision as to how a key is pressed, such as checking for modifier keys or getting the raw os keycode.
|
||||||
|
|
||||||
|
```c
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key function callback data.
|
||||||
|
* Data related to the mlx_key_hook function
|
||||||
|
*
|
||||||
|
* @param key The key that was pressed.
|
||||||
|
* @param action The action that was done with the key.
|
||||||
|
* @param os_key The os_key is unique for every key, and will have a
|
||||||
|
* different value/keycode depending on the platform.
|
||||||
|
* They may be consistent on different platforms.
|
||||||
|
* @param modifier The modifier key that was pressed, 0 if none.
|
||||||
|
*/
|
||||||
|
typedef struct mlx_key_data
|
||||||
|
{
|
||||||
|
keys_t key;
|
||||||
|
action_t action;
|
||||||
|
int32_t os_key;
|
||||||
|
modifier_key_t modifier;
|
||||||
|
} mlx_key_data_t;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function used to handle keypresses.
|
||||||
|
*
|
||||||
|
* @param[in] keydata The callback data, contains info on key, action, ...
|
||||||
|
* @param[in] param Additional parameter to pass to the function.
|
||||||
|
*/
|
||||||
|
typedef void (*mlx_keyfunc)(mlx_key_data_t keydata, void* param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function sets the key callback, which is called when a key is pressed
|
||||||
|
* on the keyboard. Useful for single key press detection.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] func The key press callback function.
|
||||||
|
* @param[in] param An additional optional parameter.
|
||||||
|
*/
|
||||||
|
void mlx_key_hook(mlx_t* mlx, mlx_keyfunc func, void* param);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Generic Hook
|
||||||
|
|
||||||
|
Generic hooks execute each frame and are useful for stuff that needs to be updated every frame.
|
||||||
|
|
||||||
|
```c
|
||||||
|
/**
|
||||||
|
* Generic loop hook for any custom hooks to add to the main loop.
|
||||||
|
* Executes a function per frame, so be careful.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] f The function.
|
||||||
|
* @param[in] param The parameter to pass onto the function.
|
||||||
|
* @returns Wether the hook was added successfuly.
|
||||||
|
*/
|
||||||
|
bool mlx_loop_hook(mlx_t* mlx, void (*f)(void*), void* param);
|
||||||
|
```
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
|
||||||
|
Here are some simple examples on how to implement each one of the hooks in a simple fashion.
|
||||||
|
|
||||||
|
## Key Hook
|
||||||
|
|
||||||
|
```c
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "MLX42/MLX42.h"
|
||||||
|
#define WIDTH 720
|
||||||
|
#define HEIGHT 480
|
||||||
|
|
||||||
|
void my_keyhook(mlx_key_data_t keydata, void* param)
|
||||||
|
{
|
||||||
|
// If we PRESS the 'J' key, print "Hello".
|
||||||
|
if (keydata.key == MLX_KEY_J && keydata.action == MLX_PRESS)
|
||||||
|
puts("Hello ");
|
||||||
|
|
||||||
|
// If we RELEASE the 'K' key, print "World".
|
||||||
|
if (keydata.key == MLX_KEY_K && keydata.action == MLX_RELEASE)
|
||||||
|
puts("World");
|
||||||
|
|
||||||
|
// If we HOLD the 'L' key, print "!".
|
||||||
|
if (keydata.key == MLX_KEY_L && keydata.action == MLX_REPEAT)
|
||||||
|
puts("!");
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t main(void)
|
||||||
|
{
|
||||||
|
mlx_t* mlx;
|
||||||
|
|
||||||
|
if (!(mlx = mlx_init(WIDTH, HEIGHT, "MLX42", true)))
|
||||||
|
return (EXIT_FAILURE);
|
||||||
|
|
||||||
|
mlx_key_hook(mlx, &my_keyhook, NULL);
|
||||||
|
mlx_loop(mlx);
|
||||||
|
mlx_terminate(mlx);
|
||||||
|
return (EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Scroll Example
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "MLX42/MLX42.h"
|
||||||
|
#define WIDTH 720
|
||||||
|
#define HEIGHT 480
|
||||||
|
|
||||||
|
void my_scrollhook(double xdelta, double ydelta, void* param)
|
||||||
|
{
|
||||||
|
// Simple up or down detection.
|
||||||
|
if (ydelta > 0)
|
||||||
|
puts("Up!");
|
||||||
|
else if (ydelta < 0)
|
||||||
|
puts("Down!");
|
||||||
|
|
||||||
|
// Can also detect a mousewheel that goes along the X (e.g: MX Master 3)
|
||||||
|
if (xdelta < 0)
|
||||||
|
puts("Sliiiide to the left!");
|
||||||
|
else if (xdelta > 0)
|
||||||
|
puts("Sliiiide to the right!");
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t main(void)
|
||||||
|
{
|
||||||
|
mlx_t* mlx;
|
||||||
|
|
||||||
|
if (!(mlx = mlx_init(WIDTH, HEIGHT, "MLX42", true)))
|
||||||
|
return (EXIT_FAILURE);
|
||||||
|
|
||||||
|
mlx_scroll_hook(mlx, &my_scrollhook, NULL);
|
||||||
|
mlx_loop(mlx);
|
||||||
|
mlx_terminate(mlx);
|
||||||
|
return (EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
```
|
122
MLX42/docs/Images.md
Normal file
122
MLX42/docs/Images.md
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
<!----------------------------------------------------------------------------
|
||||||
|
Copyright @ 2021-2022 Codam Coding College. All rights reserved.
|
||||||
|
See copyright and license notice in the root project for more information.
|
||||||
|
----------------------------------------------------------------------------->
|
||||||
|
|
||||||
|
# Images
|
||||||
|
|
||||||
|
Images are like a canvas for a painting, they are used to display pixel information onto the window and work with something called instances.
|
||||||
|
Instances are copies of the canvas and let you display an image multiple times throughout the window. The idea behind it is that you already
|
||||||
|
have the pixel information in memory and you can simply create duplicates everywhere.
|
||||||
|
|
||||||
|
Each instance has an X, Y and Z parameter to determine their position and depth.
|
||||||
|
A change in the image's buffer results in a change for all currently displayed instances.
|
||||||
|
|
||||||
|
An image on its own is very simple:
|
||||||
|
```c
|
||||||
|
/**
|
||||||
|
* An image with an individual buffer that can be rendered.
|
||||||
|
* Any value can be modified except the width/height and context.
|
||||||
|
*
|
||||||
|
* @param width The width of the image.
|
||||||
|
* @param height The height of the image.
|
||||||
|
* @param pixels The literal pixel data.
|
||||||
|
* @param instances An instance carries the X, Y, Z location data.
|
||||||
|
* @param count The element count of the instances array.
|
||||||
|
* @param enabled If true the image is drawn onto the screen, else it's not.
|
||||||
|
* @param context Abstracted OpenGL data.
|
||||||
|
*/
|
||||||
|
typedef struct mlx_image
|
||||||
|
{
|
||||||
|
const uint32_t width;
|
||||||
|
const uint32_t height;
|
||||||
|
uint8_t* pixels;
|
||||||
|
mlx_instance_t* instances;
|
||||||
|
int32_t count;
|
||||||
|
bool enabled;
|
||||||
|
void* context;
|
||||||
|
} mlx_image_t;
|
||||||
|
```
|
||||||
|
|
||||||
|
To display the image all that is needed is to call the `mlx_image_to_window` function to create a new copy/instance:
|
||||||
|
```c
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <memory.h>
|
||||||
|
#include "MLX42/MLX42.h"
|
||||||
|
#define WIDTH 5120
|
||||||
|
#define HEIGHT 2880
|
||||||
|
|
||||||
|
static void error(void)
|
||||||
|
{
|
||||||
|
puts(mlx_strerror(mlx_errno));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t main(void)
|
||||||
|
{
|
||||||
|
// Start mlx
|
||||||
|
mlx_t* mlx = mlx_init(WIDTH, HEIGHT, "Test", true);
|
||||||
|
if (!mlx)
|
||||||
|
error();
|
||||||
|
|
||||||
|
// Create a new image
|
||||||
|
mlx_image_t* img = mlx_new_image(mlx, 512, 512);
|
||||||
|
if (!img)
|
||||||
|
error();
|
||||||
|
|
||||||
|
// Set every pixel to white
|
||||||
|
memset(img->pixels, 255, img->width * img->height * sizeof(int32_t));
|
||||||
|
|
||||||
|
// Display an instance of the image
|
||||||
|
if (mlx_image_to_window(mlx, img, 0, 0) < 0)
|
||||||
|
error();
|
||||||
|
|
||||||
|
mlx_loop(mlx);
|
||||||
|
|
||||||
|
// Optional, terminate will clean up any leftovers, this is just to demonstrate.
|
||||||
|
mlx_delete_image(mlx, img);
|
||||||
|
mlx_terminate(mlx);
|
||||||
|
return (EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After we have put an instance of an image onto the window we can simply change the position of the image at any time
|
||||||
|
we want it to be moved:
|
||||||
|
```c
|
||||||
|
// Modify the x & y position of an already existing instance.
|
||||||
|
img->instances[0].x += 5;
|
||||||
|
img->instances[0].y += 5;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Transparency
|
||||||
|
In regards to transparency, aka the `z` value, use `mlx_set_instance_depth` to set the z/depth value of the image.
|
||||||
|
The z value determines the depth of the image, as in, is it in the foreground or background.
|
||||||
|
|
||||||
|
If two instances are on the same z layer and are transparent, the transparency breaks and the instances cut off each other.
|
||||||
|
To prevent this by default any new instances put onto window will be on their own layer.
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
A noticeable feature of MLX42 is that it partly takes care of the rendering for you, that is, after you've created your image you just display it
|
||||||
|
and after that feel free to modify it without having to re-put it onto the window. In short MLX takes care of updating your images at all times.
|
||||||
|
|
||||||
|
Internally this is done via a render queue, anytime the `mlx_image_to_window` function is used, a new entry is added to a linked list.
|
||||||
|
Every frame MLX will iterate over this linked list and execute a drawcall to draw that image onto the window.
|
||||||
|
|
||||||
|
## Common functions
|
||||||
|
|
||||||
|
```c
|
||||||
|
// Creates a whole new image.
|
||||||
|
mlx_image_t* mlx_new_image(mlx_t* mlx, uint16_t width, uint16_t height)
|
||||||
|
```
|
||||||
|
|
||||||
|
```c
|
||||||
|
// Creates a new instance/copy of an already existing image.
|
||||||
|
void mlx_image_to_window(mlx_image_t* img, int32_t x, int32_t y)
|
||||||
|
```
|
||||||
|
|
||||||
|
```c
|
||||||
|
// Deletes an image and removes it from the render queue.
|
||||||
|
void mlx_delete_image(mlx* mlx, mlx_image_t* image)
|
||||||
|
```
|
47
MLX42/docs/Input.md
Normal file
47
MLX42/docs/Input.md
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<!----------------------------------------------------------------------------
|
||||||
|
Copyright @ 2021-2022 Codam Coding College. All rights reserved.
|
||||||
|
See copyright and license notice in the root project for more information.
|
||||||
|
----------------------------------------------------------------------------->
|
||||||
|
|
||||||
|
# Input methods
|
||||||
|
|
||||||
|
MLX42 provides various ways of detecting input, you can read about all the available hooks on the [Hooks](./Hooks.md) page.
|
||||||
|
|
||||||
|
## Key Detection
|
||||||
|
|
||||||
|
### Generic Hook + function
|
||||||
|
|
||||||
|
The easiest way of detecting continuous keypressing is via a generic hook and then checking if the specific key is down.
|
||||||
|
This is the 'traditional' way of detecting if a key is down even in modern game engines. It provides the quickest feedback and if it's used to, say, move a character, the smoothest result.
|
||||||
|
|
||||||
|
```c
|
||||||
|
void hook(void *param)
|
||||||
|
{
|
||||||
|
mlx_t *mlx;
|
||||||
|
|
||||||
|
mlx = param;
|
||||||
|
if (mlx_is_key_down(param, MLX_KEY_ESCAPE))
|
||||||
|
mlx_close_window(param);
|
||||||
|
if (mlx_is_key_down(param, MLX_KEY_UP))
|
||||||
|
g_img->instances[0].y -= 5;
|
||||||
|
if (mlx_is_key_down(param, MLX_KEY_DOWN))
|
||||||
|
g_img->instances[0].y += 5;
|
||||||
|
if (mlx_is_key_down(param, MLX_KEY_LEFT))
|
||||||
|
g_img->instances[0].x -= 5;
|
||||||
|
if (mlx_is_key_down(param, MLX_KEY_RIGHT))
|
||||||
|
g_img->instances[0].x += 5;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Hook Function
|
||||||
|
|
||||||
|
For more exact input detection such as checking if the key was pressed with `Alt` or `ctrl` you should use the actual Key hook.
|
||||||
|
Keep in mind that using a keyhook results in a slower feedback compared to using a generic hook but grants you more control in key detection.
|
||||||
|
|
||||||
|
```c
|
||||||
|
void key_hook(mlx_key_data_t keydata, void* param)
|
||||||
|
{
|
||||||
|
if (keydata.key == MLX_KEY_A && keydata.action == MLX_RELEASE && keydata.modifier == MLX_CONTROL)
|
||||||
|
puts("Gotta grab it all!");
|
||||||
|
}
|
||||||
|
```
|
37
MLX42/docs/Shaders.md
Normal file
37
MLX42/docs/Shaders.md
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<!----------------------------------------------------------------------------
|
||||||
|
Copyright @ 2021-2022 Codam Coding College. All rights reserved.
|
||||||
|
See copyright and license notice in the root project for more information.
|
||||||
|
----------------------------------------------------------------------------->
|
||||||
|
|
||||||
|
# Shaders
|
||||||
|
|
||||||
|
In computer graphics, a shader is a type of computer program used for shading in 3D/2D scenes (the production of appropriate levels of light, darkness, and color in a rendered image). MLX42 exposes the shaders and compiles them into the library for portability.
|
||||||
|
|
||||||
|
```glsl
|
||||||
|
|
||||||
|
// Example of shader code, GLSL is similar to C but not quite.
|
||||||
|
|
||||||
|
#version 330 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 aPos;
|
||||||
|
layout(location = 1) in vec2 aTexCoord;
|
||||||
|
|
||||||
|
out vec2 TexCoord;
|
||||||
|
uniform mat4 ProjMatrix;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = ProjMatrix * vec4(aPos, 1.0);
|
||||||
|
TexCoord = aTexCoord;
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Beware
|
||||||
|
|
||||||
|
Shaders aren't really meant to be used by students but are more there for the convenience of developers. (though some advanced students might make some use of them)
|
||||||
|
|
||||||
|
# Compiliation
|
||||||
|
|
||||||
|
Shaders are converted into a `.c` appropriate format and then compiled into the library and referenced via a `extern` global variable appropriately named `vert_shader` & `frag_shader`. The reason this is done is to keep the final game/executable portable, that is being able to use it at any given location within a filesystem, while still being easy to work on the shaders instead of having to mess with it in the `.c` files directly.
|
||||||
|
|
82
MLX42/docs/Textures.md
Normal file
82
MLX42/docs/Textures.md
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
<!----------------------------------------------------------------------------
|
||||||
|
Copyright @ 2021-2022 Codam Coding College. All rights reserved.
|
||||||
|
See copyright and license notice in the root project for more information.
|
||||||
|
----------------------------------------------------------------------------->
|
||||||
|
|
||||||
|
# Textures
|
||||||
|
|
||||||
|
Textures are disk loaded images stored in memory and hold a buffer of pixel data along with information
|
||||||
|
about the image such as width, height, and bytes per pixel.
|
||||||
|
|
||||||
|
Textures on their own are not displayed to the screen but have to be displayed using [Images](./Images.md).
|
||||||
|
To do so you can use the `mlx_texture_to_image` function that creates an image large enough to store the
|
||||||
|
texture which then can be displayed.
|
||||||
|
|
||||||
|
## Textures vs Images
|
||||||
|
|
||||||
|
There might be a bit of confusion at first between what an image and a texture is.
|
||||||
|
|
||||||
|
Textures:
|
||||||
|
* Can be interpreted as a painter's "color palette".
|
||||||
|
* Created by loading an image file FROM disk.
|
||||||
|
* Simply contain the pixels, width, height and bytes per pixel information.
|
||||||
|
* Do not get displayed on the window directly.
|
||||||
|
|
||||||
|
Images:
|
||||||
|
* Can be interpreted as a painter's "canvas".
|
||||||
|
* Can be created FROM a texture or an empty buffer!
|
||||||
|
* Carries more information besides what the image buffer is such as instance count.
|
||||||
|
* Also holds pixel data but is shared among its instances, it is not loaded from disk but stored in memory.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
To summarize, in order to display a sprite image onto our window we would first load the texture from
|
||||||
|
disk into our memory and store the information in a `mlx_texture_t*`. After that we create a new `mlx_image_t*`
|
||||||
|
based on the information given by the texture and then we can display our image onto the window.
|
||||||
|
|
||||||
|
Below is a small code example of how this would be achieved:
|
||||||
|
|
||||||
|
```C
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "MLX42/MLX42.h"
|
||||||
|
#define WIDTH 512
|
||||||
|
#define HEIGHT 512
|
||||||
|
|
||||||
|
static void error(void)
|
||||||
|
{
|
||||||
|
puts(mlx_strerror(mlx_errno));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t main(void)
|
||||||
|
{
|
||||||
|
// Start mlx
|
||||||
|
mlx_t* mlx = mlx_init(WIDTH, HEIGHT, "Test", true);
|
||||||
|
if (!mlx)
|
||||||
|
error();
|
||||||
|
|
||||||
|
// Try to load the file
|
||||||
|
mlx_texture_t* texture = mlx_load_png("./temp/sus.png");
|
||||||
|
if (!texture)
|
||||||
|
error();
|
||||||
|
|
||||||
|
// Convert texture to a displayable image
|
||||||
|
mlx_image_t* img = mlx_texture_to_image(mlx, texture);
|
||||||
|
if (!img)
|
||||||
|
error();
|
||||||
|
|
||||||
|
// Display the image
|
||||||
|
if (mlx_image_to_window(mlx, img, 0, 0) < 0)
|
||||||
|
error();
|
||||||
|
|
||||||
|
mlx_loop(mlx);
|
||||||
|
|
||||||
|
// Optional, terminate will clean up any leftovers, this is just to demonstrate.
|
||||||
|
mlx_delete_image(mlx, img);
|
||||||
|
mlx_delete_texture(texture);
|
||||||
|
mlx_terminate(mlx);
|
||||||
|
return (EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
```
|
92
MLX42/docs/XPM42.md
Normal file
92
MLX42/docs/XPM42.md
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
<!----------------------------------------------------------------------------
|
||||||
|
Copyright @ 2021-2022 Codam Coding College. All rights reserved.
|
||||||
|
See copyright and license notice in the root project for more information.
|
||||||
|
----------------------------------------------------------------------------->
|
||||||
|
|
||||||
|
# XPM42
|
||||||
|
|
||||||
|
XPM42 is a custom file format made for MLX42 to provide an easy to use and understand image file format to learn how
|
||||||
|
images can be stored. The format is based on the actual [XPM3](https://en.wikipedia.org/wiki/X_PixMap) format.
|
||||||
|
|
||||||
|
An XPM file basically stores a look-up table inside of it to fetch which character corresponds to which color. Additionally in the
|
||||||
|
header there is a character per pixel count, this is due to the limitation of the amount of characters. Each 'Pixel' in the XPM data can
|
||||||
|
be represented by multiple characters.
|
||||||
|
|
||||||
|
For example `*.` would be viewed as a single pixel if the characters per pixel count was 2.
|
||||||
|
|
||||||
|
## Layout
|
||||||
|
|
||||||
|
The file format looks as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
!XPM42 <- File declaration
|
||||||
|
16 7 2 1 c <- Width | Height | Color count | Characters per Pixel | Mode (C: Color or M: Monochrome)
|
||||||
|
* #FF0000FF <- Entry always: <Char> <Space> <Hexadecimal> Colors MUST have all four channels (RGBA)
|
||||||
|
. #00000000
|
||||||
|
**..*........... <- Literal pixel data
|
||||||
|
*.*.*...........
|
||||||
|
**..*..**.**..**
|
||||||
|
*.*.*.*.*.*..*.*
|
||||||
|
**..*..**.*...**
|
||||||
|
...............*
|
||||||
|
.............**.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Inner workings
|
||||||
|
|
||||||
|
Reading an XPM42 does a whole bunch of stuff but in essence it reads the file header and inserts each color entry into a hash table for fast lookups of the color value, the hash used is FNV-1a. Why, because it's an easy to use hash and also my favourite. After the header is read and the color values are inserted into the table each line is then read and each character is processed and inserted into the pixel buffer of the XPM. There is no collision checking for the lookup table, so artefacts may be present.
|
||||||
|
|
||||||
|
## Tools
|
||||||
|
|
||||||
|
In the root of the repository is a tools directory in which a python script can convert an existing XPM3 file to XPM42.
|
||||||
|
Use this script if you wish to use the XPM42 file format.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```C
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "MLX42/MLX42.h"
|
||||||
|
#define WIDTH 5120
|
||||||
|
#define HEIGHT 2880
|
||||||
|
|
||||||
|
static void error(void)
|
||||||
|
{
|
||||||
|
puts(mlx_strerror(mlx_errno));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t main(void)
|
||||||
|
{
|
||||||
|
// Start mlx
|
||||||
|
mlx_t* mlx = mlx_init(WIDTH, HEIGHT, "Test", true);
|
||||||
|
if (!mlx)
|
||||||
|
error();
|
||||||
|
|
||||||
|
// Try to load the file
|
||||||
|
xpm_t* xpm = mlx_load_xpm42("./temp/42.xpm42");
|
||||||
|
if (!xpm)
|
||||||
|
error();
|
||||||
|
|
||||||
|
// Convert texture to a displayable image
|
||||||
|
mlx_image_t* img = mlx_texture_to_image(mlx, &xpm->texture);
|
||||||
|
if (!img)
|
||||||
|
error();
|
||||||
|
|
||||||
|
// Display the image
|
||||||
|
if (mlx_image_to_window(mlx, img, 0, 0) < 0)
|
||||||
|
error();
|
||||||
|
|
||||||
|
mlx_loop(mlx);
|
||||||
|
|
||||||
|
// Optional, terminate will clean up any leftovers, this is just to demonstrate.
|
||||||
|
mlx_delete_image(mlx, img);
|
||||||
|
mlx_delete_xpm42(xpm);
|
||||||
|
mlx_terminate(mlx);
|
||||||
|
return (EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
![Example](./assets/XPM_Demo.png)
|
BIN
MLX42/docs/assets/demo.gif
Normal file
BIN
MLX42/docs/assets/demo.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.7 MiB |
BIN
MLX42/docs/assets/logo.png
Normal file
BIN
MLX42/docs/assets/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.8 KiB |
143
MLX42/docs/index.md
Normal file
143
MLX42/docs/index.md
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
<!----------------------------------------------------------------------------
|
||||||
|
Copyright @ 2021-2022 Codam Coding College. All rights reserved.
|
||||||
|
See copyright and license notice in the root project for more information.
|
||||||
|
----------------------------------------------------------------------------->
|
||||||
|
|
||||||
|
</br>
|
||||||
|
<div align="center">
|
||||||
|
<img src="./assets/logo.png" alt="42MLX_Logo">
|
||||||
|
</div>
|
||||||
|
<div align="center" style="margin-top: 8px;">
|
||||||
|
<sub>Written by <a href="https://portfolio.w2wizard.dev/">W2.Wizard</a> for the 42 Network</sub>
|
||||||
|
</div>
|
||||||
|
</br>
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<h1>Welcome to the MLX42 documentation</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
# Introduction
|
||||||
|
|
||||||
|
MLX42 is a performant, easy to use, cross-platform windowing library to create
|
||||||
|
graphical applications without having to work directly with the native Windowing
|
||||||
|
Framework of the given operating system.
|
||||||
|
|
||||||
|
Additionally it provides primitive tools for drawing onto the window such as
|
||||||
|
displaying images from disk or creating a drawing surface to draw pixels on.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Toc
|
||||||
|
|
||||||
|
* [Basics](./Basics.md)
|
||||||
|
* [Colors](./Colors.md)
|
||||||
|
* [Functions](./Functions.md)
|
||||||
|
* [Hooks](./Hooks.md)
|
||||||
|
* [Images](./Images.md)
|
||||||
|
* [Input](./Input.md)
|
||||||
|
* [Shaders](./Shaders.md)
|
||||||
|
* [Textures](./Textures.md)
|
||||||
|
* [XPM42](./XPM42.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
Currently supported operating systems:
|
||||||
|
| Operating system | Version |
|
||||||
|
|------------------ |--------------------------------------------- |
|
||||||
|
| `Windows NT` | Windows 7 - Windows 11 |
|
||||||
|
| `MacOS` | Mojave - Monterey (Including Apple Silicon) |
|
||||||
|
| `Linux` | Anything running X11 / Wayland |
|
||||||
|
|
||||||
|
## Initialization
|
||||||
|
|
||||||
|
The very first step for initialization is to execute the mlx_init function.
|
||||||
|
It is responsible for setting up the GLFW windowing library which
|
||||||
|
creates a connection between your software and the display. It also loads the
|
||||||
|
OpenGL function pointers, compiling the shaders and more.
|
||||||
|
|
||||||
|
It returns a mlx_t* which is a structure containing the current window instance.
|
||||||
|
With this instance you can manipulate, hook onto and control what happens inside
|
||||||
|
your window instance. For example you would use it to send graphical instructions such as
|
||||||
|
creating an image, which is used to display pixel data. You can also detect key
|
||||||
|
interactions such as checking if the W, A, S or D key is currently being pressed.
|
||||||
|
|
||||||
|
| Function | Description |
|
||||||
|
|-------------------|--------------------------------------------------------------|
|
||||||
|
| `mlx_init()` | Initialize and run a new window instance. |
|
||||||
|
| `mlx_loop()` | Keep the window open as long as a shutdown is not requested. |
|
||||||
|
| `mlx_terminate()` | Destroy and clean up all images and mlx resources. |
|
||||||
|
|
||||||
|
If mlx_init() fails to set up the connection to the graphical system, it will
|
||||||
|
return NULL, otherwise a non-null pointer is returned as a handle for the window.
|
||||||
|
|
||||||
|
## Linking
|
||||||
|
|
||||||
|
In order to use the functions in MLX, you'll need to link it with your application.
|
||||||
|
|
||||||
|
To do this, simply add the following arguments at the linking stage:
|
||||||
|
| Operating System | Flags |
|
||||||
|
|------------------|---------------------------------------------------------------|
|
||||||
|
| `Windows NT` | -lglfw3 -lopengl32 -lgdi32 |
|
||||||
|
| `MacOS` | -lglfw(3) -framework Cocoa -framework OpenGL -framework IOKit |
|
||||||
|
| `Linux` | -ldl -lglfw(3) -pthread -lm |
|
||||||
|
|
||||||
|
**NOTE: For some UNIX systems the flag for glfw might be with or without a 3 at the end.**
|
||||||
|
|
||||||
|
## Build options
|
||||||
|
|
||||||
|
When building MLX42 you can pass certain build options to cmake.
|
||||||
|
|
||||||
|
The options are passed as follows `cmake -DDEBUG=1 -DGLFW_FETCH=0`.
|
||||||
|
|
||||||
|
### Available options
|
||||||
|
|
||||||
|
* `DEBUG`: Enables assertion macros and compiles with -g in order for debugging with lldb.
|
||||||
|
* `GLFW_FETCH`: Fetches GLFW if it can't be found on the system at all, allows you to then install it with `sudo make install` under the `build/_deps` folder.
|
||||||
|
|
||||||
|
## Debugging
|
||||||
|
|
||||||
|
MLX was designed with ease of debugging in mind, therefore if the project is built with
|
||||||
|
**cmake -DDEBUG=1** it will keep in the assertion macros and notify you of any bad input
|
||||||
|
given to functions. Additionally it comes with its own runtime error checking via
|
||||||
|
**mlx_errno** and **mlx_strerror** to properly identify what went wrong during the runtime
|
||||||
|
of the library.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
Keep in mind that while technically MLX42
|
||||||
|
does support multiple window instances it currently has no functional support for
|
||||||
|
it. That is, no proper way of handling multiple windows.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## F.A.Q
|
||||||
|
|
||||||
|
Q: **_"It'S NoT In ThE SuBjeCt!"_**
|
||||||
|
|
||||||
|
A: So what? Subjects can change and so if something is not working correctly it should be replaced. Sure you can argue this point but you can also be the reason that it CAN be in the subject instead. Have an open mind :)
|
||||||
|
|
||||||
|
Q: **_"Ok, so, can I use it ?"_**
|
||||||
|
|
||||||
|
A: Officially, _no_. However, ask your head of studies first about using it, see what they think. Some students might be evangelical enthusiasts about what is stated in the subject and are technically in every right to fail you as long as this library is not endorsed, if you were to ask me (W2) then yes why not?
|
||||||
|
|
||||||
|
Q: **_"Is it faster?"_**
|
||||||
|
|
||||||
|
A: From my personal projects there was a considerable peformance gain, especially when compiled with `-Ofast`. Projects such as FDF could rotate their maps mindblowingly smooth and even larger maps with a width and height of 1000+ points moved/rotated relatively smooth, so in short, yes.
|
||||||
|
|
||||||
|
Q: **_"Can I just drag and drop it into my old project and just not do anything?"_**
|
||||||
|
|
||||||
|
A: Well, um uh, no ?? That's not how libraries work. Sure they target and do sort of the same thing but the functions each library provides are too different, even a little bit in terms of behavior. And no there is no easy way to convert from the "old" to the "new" it will be somewhat tedious work.
|
||||||
|
|
||||||
|
Q: **_"We should be able to deal with the fact that MiniLibX is not perfect, it is by design and makes us better programmers."_**
|
||||||
|
|
||||||
|
A: Struggle does bring out the best in most people but it is also not ideal in this case. I think so at least, that it's really expected that libraries that are publicly available should be usable, stable, easy to use and well documented. Nobody uses a library because it is annoying to work with and afterwards think to themselves they have learned something after they are done struggling. The only thing people learn from this is how to navigate around the shortcomings instead.
|
||||||
|
|
||||||
|
Q: **_"Why not use some other library? Why this one and not any other library."_**
|
||||||
|
|
||||||
|
A: It is your choice what to use! I wrote this in my free time in an attempt to introduce some good change and to improve the learning experience at 42. If you don't like my library at least let me know what it is so I can improve on it.
|
||||||
|
|
||||||
|
Q: **_"Do you hate MiniLibX? Is this some personal vendetta, do you work for the CIA ?"_**
|
||||||
|
|
||||||
|
A: No, I just want to improve 42, that's it.
|
311
MLX42/include/KHR/khrplatform.h
Normal file
311
MLX42/include/KHR/khrplatform.h
Normal file
@ -0,0 +1,311 @@
|
|||||||
|
#ifndef __khrplatform_h_
|
||||||
|
#define __khrplatform_h_
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Copyright (c) 2008-2018 The Khronos Group Inc.
|
||||||
|
**
|
||||||
|
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
** copy of this software and/or associated documentation files (the
|
||||||
|
** "Materials"), to deal in the Materials without restriction, including
|
||||||
|
** without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||||
|
** permit persons to whom the Materials are furnished to do so, subject to
|
||||||
|
** the following conditions:
|
||||||
|
**
|
||||||
|
** The above copyright notice and this permission notice shall be included
|
||||||
|
** in all copies or substantial portions of the Materials.
|
||||||
|
**
|
||||||
|
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Khronos platform-specific types and definitions.
|
||||||
|
*
|
||||||
|
* The master copy of khrplatform.h is maintained in the Khronos EGL
|
||||||
|
* Registry repository at https://github.com/KhronosGroup/EGL-Registry
|
||||||
|
* The last semantic modification to khrplatform.h was at commit ID:
|
||||||
|
* 67a3e0864c2d75ea5287b9f3d2eb74a745936692
|
||||||
|
*
|
||||||
|
* Adopters may modify this file to suit their platform. Adopters are
|
||||||
|
* encouraged to submit platform specific modifications to the Khronos
|
||||||
|
* group so that they can be included in future versions of this file.
|
||||||
|
* Please submit changes by filing pull requests or issues on
|
||||||
|
* the EGL Registry repository linked above.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* See the Implementer's Guidelines for information about where this file
|
||||||
|
* should be located on your system and for more details of its use:
|
||||||
|
* http://www.khronos.org/registry/implementers_guide.pdf
|
||||||
|
*
|
||||||
|
* This file should be included as
|
||||||
|
* #include <KHR/khrplatform.h>
|
||||||
|
* by Khronos client API header files that use its types and defines.
|
||||||
|
*
|
||||||
|
* The types in khrplatform.h should only be used to define API-specific types.
|
||||||
|
*
|
||||||
|
* Types defined in khrplatform.h:
|
||||||
|
* khronos_int8_t signed 8 bit
|
||||||
|
* khronos_uint8_t unsigned 8 bit
|
||||||
|
* khronos_int16_t signed 16 bit
|
||||||
|
* khronos_uint16_t unsigned 16 bit
|
||||||
|
* khronos_int32_t signed 32 bit
|
||||||
|
* khronos_uint32_t unsigned 32 bit
|
||||||
|
* khronos_int64_t signed 64 bit
|
||||||
|
* khronos_uint64_t unsigned 64 bit
|
||||||
|
* khronos_intptr_t signed same number of bits as a pointer
|
||||||
|
* khronos_uintptr_t unsigned same number of bits as a pointer
|
||||||
|
* khronos_ssize_t signed size
|
||||||
|
* khronos_usize_t unsigned size
|
||||||
|
* khronos_float_t signed 32 bit floating point
|
||||||
|
* khronos_time_ns_t unsigned 64 bit time in nanoseconds
|
||||||
|
* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
|
||||||
|
* nanoseconds
|
||||||
|
* khronos_stime_nanoseconds_t signed time interval in nanoseconds
|
||||||
|
* khronos_boolean_enum_t enumerated boolean type. This should
|
||||||
|
* only be used as a base type when a client API's boolean type is
|
||||||
|
* an enum. Client APIs which use an integer or other type for
|
||||||
|
* booleans cannot use this as the base type for their boolean.
|
||||||
|
*
|
||||||
|
* Tokens defined in khrplatform.h:
|
||||||
|
*
|
||||||
|
* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
|
||||||
|
*
|
||||||
|
* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
|
||||||
|
* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
|
||||||
|
*
|
||||||
|
* Calling convention macros defined in this file:
|
||||||
|
* KHRONOS_APICALL
|
||||||
|
* KHRONOS_APIENTRY
|
||||||
|
* KHRONOS_APIATTRIBUTES
|
||||||
|
*
|
||||||
|
* These may be used in function prototypes as:
|
||||||
|
*
|
||||||
|
* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
|
||||||
|
* int arg1,
|
||||||
|
* int arg2) KHRONOS_APIATTRIBUTES;
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
|
||||||
|
# define KHRONOS_STATIC 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* Definition of KHRONOS_APICALL
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
* This precedes the return type of the function in the function prototype.
|
||||||
|
*/
|
||||||
|
#if defined(KHRONOS_STATIC)
|
||||||
|
/* If the preprocessor constant KHRONOS_STATIC is defined, make the
|
||||||
|
* header compatible with static linking. */
|
||||||
|
# define KHRONOS_APICALL
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
# define KHRONOS_APICALL __declspec(dllimport)
|
||||||
|
#elif defined (__SYMBIAN32__)
|
||||||
|
# define KHRONOS_APICALL IMPORT_C
|
||||||
|
#elif defined(__ANDROID__)
|
||||||
|
# define KHRONOS_APICALL __attribute__((visibility("default")))
|
||||||
|
#else
|
||||||
|
# define KHRONOS_APICALL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* Definition of KHRONOS_APIENTRY
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
* This follows the return type of the function and precedes the function
|
||||||
|
* name in the function prototype.
|
||||||
|
*/
|
||||||
|
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
|
||||||
|
/* Win32 but not WinCE */
|
||||||
|
# define KHRONOS_APIENTRY __stdcall
|
||||||
|
#else
|
||||||
|
# define KHRONOS_APIENTRY
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* Definition of KHRONOS_APIATTRIBUTES
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
* This follows the closing parenthesis of the function prototype arguments.
|
||||||
|
*/
|
||||||
|
#if defined (__ARMCC_2__)
|
||||||
|
#define KHRONOS_APIATTRIBUTES __softfp
|
||||||
|
#else
|
||||||
|
#define KHRONOS_APIATTRIBUTES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* basic type definitions
|
||||||
|
*-----------------------------------------------------------------------*/
|
||||||
|
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Using <stdint.h>
|
||||||
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
typedef int32_t khronos_int32_t;
|
||||||
|
typedef uint32_t khronos_uint32_t;
|
||||||
|
typedef int64_t khronos_int64_t;
|
||||||
|
typedef uint64_t khronos_uint64_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
/*
|
||||||
|
* To support platform where unsigned long cannot be used interchangeably with
|
||||||
|
* inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t.
|
||||||
|
* Ideally, we could just use (u)intptr_t everywhere, but this could result in
|
||||||
|
* ABI breakage if khronos_uintptr_t is changed from unsigned long to
|
||||||
|
* unsigned long long or similar (this results in different C++ name mangling).
|
||||||
|
* To avoid changes for existing platforms, we restrict usage of intptr_t to
|
||||||
|
* platforms where the size of a pointer is larger than the size of long.
|
||||||
|
*/
|
||||||
|
#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__)
|
||||||
|
#if __SIZEOF_POINTER__ > __SIZEOF_LONG__
|
||||||
|
#define KHRONOS_USE_INTPTR_T
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined(__VMS ) || defined(__sgi)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Using <inttypes.h>
|
||||||
|
*/
|
||||||
|
#include <inttypes.h>
|
||||||
|
typedef int32_t khronos_int32_t;
|
||||||
|
typedef uint32_t khronos_uint32_t;
|
||||||
|
typedef int64_t khronos_int64_t;
|
||||||
|
typedef uint64_t khronos_uint64_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
|
||||||
|
#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Win32
|
||||||
|
*/
|
||||||
|
typedef __int32 khronos_int32_t;
|
||||||
|
typedef unsigned __int32 khronos_uint32_t;
|
||||||
|
typedef __int64 khronos_int64_t;
|
||||||
|
typedef unsigned __int64 khronos_uint64_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
|
||||||
|
#elif defined(__sun__) || defined(__digital__)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sun or Digital
|
||||||
|
*/
|
||||||
|
typedef int khronos_int32_t;
|
||||||
|
typedef unsigned int khronos_uint32_t;
|
||||||
|
#if defined(__arch64__) || defined(_LP64)
|
||||||
|
typedef long int khronos_int64_t;
|
||||||
|
typedef unsigned long int khronos_uint64_t;
|
||||||
|
#else
|
||||||
|
typedef long long int khronos_int64_t;
|
||||||
|
typedef unsigned long long int khronos_uint64_t;
|
||||||
|
#endif /* __arch64__ */
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
|
||||||
|
#elif 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hypothetical platform with no float or int64 support
|
||||||
|
*/
|
||||||
|
typedef int khronos_int32_t;
|
||||||
|
typedef unsigned int khronos_uint32_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 0
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 0
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generic fallback
|
||||||
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
typedef int32_t khronos_int32_t;
|
||||||
|
typedef uint32_t khronos_uint32_t;
|
||||||
|
typedef int64_t khronos_int64_t;
|
||||||
|
typedef uint64_t khronos_uint64_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Types that are (so far) the same on all platforms
|
||||||
|
*/
|
||||||
|
typedef signed char khronos_int8_t;
|
||||||
|
typedef unsigned char khronos_uint8_t;
|
||||||
|
typedef signed short int khronos_int16_t;
|
||||||
|
typedef unsigned short int khronos_uint16_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Types that differ between LLP64 and LP64 architectures - in LLP64,
|
||||||
|
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
|
||||||
|
* to be the only LLP64 architecture in current use.
|
||||||
|
*/
|
||||||
|
#ifdef KHRONOS_USE_INTPTR_T
|
||||||
|
typedef intptr_t khronos_intptr_t;
|
||||||
|
typedef uintptr_t khronos_uintptr_t;
|
||||||
|
#elif defined(_WIN64)
|
||||||
|
typedef signed long long int khronos_intptr_t;
|
||||||
|
typedef unsigned long long int khronos_uintptr_t;
|
||||||
|
#else
|
||||||
|
typedef signed long int khronos_intptr_t;
|
||||||
|
typedef unsigned long int khronos_uintptr_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN64)
|
||||||
|
typedef signed long long int khronos_ssize_t;
|
||||||
|
typedef unsigned long long int khronos_usize_t;
|
||||||
|
#else
|
||||||
|
typedef signed long int khronos_ssize_t;
|
||||||
|
typedef unsigned long int khronos_usize_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if KHRONOS_SUPPORT_FLOAT
|
||||||
|
/*
|
||||||
|
* Float type
|
||||||
|
*/
|
||||||
|
typedef float khronos_float_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if KHRONOS_SUPPORT_INT64
|
||||||
|
/* Time types
|
||||||
|
*
|
||||||
|
* These types can be used to represent a time interval in nanoseconds or
|
||||||
|
* an absolute Unadjusted System Time. Unadjusted System Time is the number
|
||||||
|
* of nanoseconds since some arbitrary system event (e.g. since the last
|
||||||
|
* time the system booted). The Unadjusted System Time is an unsigned
|
||||||
|
* 64 bit value that wraps back to 0 every 584 years. Time intervals
|
||||||
|
* may be either signed or unsigned.
|
||||||
|
*/
|
||||||
|
typedef khronos_uint64_t khronos_utime_nanoseconds_t;
|
||||||
|
typedef khronos_int64_t khronos_stime_nanoseconds_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dummy value used to pad enum types to 32 bits.
|
||||||
|
*/
|
||||||
|
#ifndef KHRONOS_MAX_ENUM
|
||||||
|
#define KHRONOS_MAX_ENUM 0x7FFFFFFF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enumerated boolean type
|
||||||
|
*
|
||||||
|
* Values other than zero should be considered to be true. Therefore
|
||||||
|
* comparisons should not be made against KHRONOS_TRUE.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
KHRONOS_FALSE = 0,
|
||||||
|
KHRONOS_TRUE = 1,
|
||||||
|
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
|
||||||
|
} khronos_boolean_enum_t;
|
||||||
|
|
||||||
|
#endif /* __khrplatform_h_ */
|
718
MLX42/include/MLX42/MLX42.h
Normal file
718
MLX42/include/MLX42/MLX42.h
Normal file
@ -0,0 +1,718 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* :::::::: */
|
||||||
|
/* MLX42_Keys.h :+: :+: */
|
||||||
|
/* +:+ */
|
||||||
|
/* By: W2Wizard <main@w2wizard.dev> +#+ */
|
||||||
|
/* +#+ */
|
||||||
|
/* Created: 2021/12/28 02:29:06 by W2Wizard #+# #+# */
|
||||||
|
/* Updated: 2023/03/30 16:23:19 by ntamayo- ######## odam.nl */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A cross-platform OpenGL graphics library based on the idea that MiniLibX
|
||||||
|
* provides. Just quite a bit better, in terms of code quality & performance.
|
||||||
|
*
|
||||||
|
* As for the few void* present in some structs and functions and
|
||||||
|
* why MLX is split into two different headers, so to speak,
|
||||||
|
* it's mainly for abstraction. Most users won't have a need for the inner
|
||||||
|
* workings of MLX (shaders, ...) and it also helps keep MLX nice and tidy.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MLX42_H
|
||||||
|
# define MLX42_H
|
||||||
|
# include <stdint.h>
|
||||||
|
# include <stdbool.h>
|
||||||
|
# include "MLX42_Input.h"
|
||||||
|
# ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base object for disk loaded textures.
|
||||||
|
* It contains rudementary information about the texture.
|
||||||
|
*
|
||||||
|
* @param width The width of the texture.
|
||||||
|
* @param height The height of the texture.
|
||||||
|
* @param pixels The literal pixel data.
|
||||||
|
* @param bytes_per_pixel The amount of bytes in a pixel, always 4.
|
||||||
|
*/
|
||||||
|
typedef struct mlx_texture
|
||||||
|
{
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height;
|
||||||
|
uint8_t bytes_per_pixel;
|
||||||
|
uint8_t* pixels;
|
||||||
|
} mlx_texture_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Struct containing data regarding an XPM image.
|
||||||
|
*
|
||||||
|
* @param texture The texture data of the XPM.
|
||||||
|
* @param color_count The amount of colors available.
|
||||||
|
* @param cpp The amount of characters per pixel.
|
||||||
|
* @param mode The color mode, either (c)olor or (m)onochrome.
|
||||||
|
*/
|
||||||
|
typedef struct xpm
|
||||||
|
{
|
||||||
|
mlx_texture_t texture;
|
||||||
|
int32_t color_count;
|
||||||
|
int32_t cpp;
|
||||||
|
char mode;
|
||||||
|
} xpm_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An image instance can be summarized as just a simple
|
||||||
|
* x, y & z coordinate.
|
||||||
|
*
|
||||||
|
* Coordinates start from the top left of the screen at 0,0 and increase
|
||||||
|
* towards the bottom right.
|
||||||
|
*
|
||||||
|
* NOTE: To change the z value, use mlx_set_instance_depth!
|
||||||
|
*
|
||||||
|
* @param x The x location.
|
||||||
|
* @param y The y location.
|
||||||
|
* @param z The z depth, controls if the image is on the fore or background.
|
||||||
|
* @param enabled If true, the instance is drawn, else it's not.
|
||||||
|
*/
|
||||||
|
typedef struct mlx_instance
|
||||||
|
{
|
||||||
|
int32_t x;
|
||||||
|
int32_t y;
|
||||||
|
int32_t z;
|
||||||
|
bool enabled;
|
||||||
|
} mlx_instance_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key function callback data.
|
||||||
|
* Data related to the mlx_key_hook function
|
||||||
|
*
|
||||||
|
* @param key The key that was pressed.
|
||||||
|
* @param action The action that was done with the key.
|
||||||
|
* @param os_key The os_key is unique for every key, and will have a
|
||||||
|
* different value/keycode depending on the platform.
|
||||||
|
* They may be consistent on different platforms.
|
||||||
|
* @param modifier The modifier key that was pressed, 0 if no key was pressed.
|
||||||
|
*/
|
||||||
|
typedef struct mlx_key_data
|
||||||
|
{
|
||||||
|
keys_t key;
|
||||||
|
action_t action;
|
||||||
|
int32_t os_key;
|
||||||
|
modifier_key_t modifier;
|
||||||
|
} mlx_key_data_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An image with an individual buffer that can be rendered.
|
||||||
|
* Any value can be modified except the width/height and context.
|
||||||
|
*
|
||||||
|
* @param width The width of the image.
|
||||||
|
* @param height The height of the image.
|
||||||
|
* @param pixels The literal pixel data.
|
||||||
|
* @param instances An instance carrying the X, Y and Z location data.
|
||||||
|
* @param count The element count of the instances array.
|
||||||
|
* @param enabled If true the image is drawn onto the screen, else it's not.
|
||||||
|
* @param context Abstracted OpenGL data.
|
||||||
|
*/
|
||||||
|
typedef struct mlx_image
|
||||||
|
{
|
||||||
|
const uint32_t width;
|
||||||
|
const uint32_t height;
|
||||||
|
uint8_t* pixels;
|
||||||
|
mlx_instance_t* instances;
|
||||||
|
int32_t count;
|
||||||
|
bool enabled;
|
||||||
|
void* context;
|
||||||
|
} mlx_image_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main MLX handle, carries important data in regards to the program.
|
||||||
|
* @param window The window itself.
|
||||||
|
* @param context Abstracted opengl data.
|
||||||
|
* @param width The width of the window.
|
||||||
|
* @param height The height of the window.
|
||||||
|
* @param delta_time The time difference between the previous frame
|
||||||
|
* and the current frame.
|
||||||
|
*/
|
||||||
|
typedef struct mlx
|
||||||
|
{
|
||||||
|
void* window;
|
||||||
|
void* context;
|
||||||
|
int32_t width;
|
||||||
|
int32_t height;
|
||||||
|
double delta_time;
|
||||||
|
} mlx_t;
|
||||||
|
|
||||||
|
// The error codes used to identify the correct error message.
|
||||||
|
typedef enum mlx_errno
|
||||||
|
{
|
||||||
|
MLX_SUCCESS = 0, // No Errors
|
||||||
|
MLX_INVEXT, // File has an invalid extension
|
||||||
|
MLX_INVFILE, // File was invalid / does not exist.
|
||||||
|
MLX_INVPNG, // Something is wrong with the given PNG file.
|
||||||
|
MLX_INVXPM, // Something is wrong with the given XPM file.
|
||||||
|
MLX_INVPOS, // The specified X/Y positions are out of bounds.
|
||||||
|
MLX_INVDIM, // The specified W/H dimensions are out of bounds.
|
||||||
|
MLX_INVIMG, // The provided image is invalid, might indicate mismanagement of images.
|
||||||
|
MLX_VERTFAIL, // Failed to compile the vertex shader.
|
||||||
|
MLX_FRAGFAIL, // Failed to compile the fragment shader.
|
||||||
|
MLX_SHDRFAIL, // Failed to compile the shaders.
|
||||||
|
MLX_MEMFAIL, // Dynamic memory allocation has failed.
|
||||||
|
MLX_GLADFAIL, // OpenGL loader has failed.
|
||||||
|
MLX_GLFWFAIL, // GLFW failed to initialize.
|
||||||
|
MLX_WINFAIL, // Failed to create a window.
|
||||||
|
MLX_STRTOOBIG, // The string is too big to be drawn.
|
||||||
|
MLX_ERRMAX, // Error count
|
||||||
|
} mlx_errno_t;
|
||||||
|
|
||||||
|
// Global error code from the MLX42 library, 0 on no error.
|
||||||
|
extern mlx_errno_t mlx_errno;
|
||||||
|
|
||||||
|
//= Global Settings =//
|
||||||
|
|
||||||
|
// Set these values, if necessary, before calling `mlx_init` as they define the behaviour of MLX42.
|
||||||
|
typedef enum mlx_settings
|
||||||
|
{
|
||||||
|
MLX_STRETCH_IMAGE = 0, // Should images resize with the window as it's being resized or not. Default: false
|
||||||
|
MLX_FULLSCREEN, // Should the window be in Fullscreen, note it will fullscreen at the given resolution. Default: false
|
||||||
|
MLX_MAXIMIZED, // Start the window in a maximized state, overwrites the fullscreen state if this is true. Default: false
|
||||||
|
MLX_DECORATED, // Have the window be decorated with a window bar. Default: true
|
||||||
|
MLX_HEADLESS, // Run in headless mode, no window is created. (NOTE: Still requires some form of window manager such as xvfb)
|
||||||
|
MLX_SETTINGS_MAX, // Setting count.
|
||||||
|
} mlx_settings_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function used to handle scrolling.
|
||||||
|
*
|
||||||
|
* @param[in] xdelta The mouse x delta.
|
||||||
|
* @param[in] ydelta The mouse y delta.
|
||||||
|
* @param[in] param Additional parameter to pass on to the function.
|
||||||
|
*/
|
||||||
|
typedef void (*mlx_scrollfunc)(double xdelta, double ydelta, void* param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function used to handle mouse actions.
|
||||||
|
*
|
||||||
|
* @param[in] button The mouse button/key pressed.
|
||||||
|
* @param[in] action The mouse action that took place.
|
||||||
|
* @param[in] mods The modifier keys pressed together with the mouse key.
|
||||||
|
* @param[in] param Additional parameter to pass on to the function.
|
||||||
|
*/
|
||||||
|
typedef void (*mlx_mousefunc)(mouse_key_t button, action_t action, modifier_key_t mods, void* param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function used to handle raw mouse movement.
|
||||||
|
*
|
||||||
|
* @param[in] xpos The mouse x position.
|
||||||
|
* @param[in] ypos The mouse y position.
|
||||||
|
* @param[in] param Additional parameter to pass on to the function.
|
||||||
|
*/
|
||||||
|
typedef void (*mlx_cursorfunc)(double xpos, double ypos, void* param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function used to handle key presses.
|
||||||
|
*
|
||||||
|
* @param[in] keydata The callback data, contains info on key, action, ...
|
||||||
|
* @param[in] param Additional parameter to pass on to the function.
|
||||||
|
*/
|
||||||
|
typedef void (*mlx_keyfunc)(mlx_key_data_t keydata, void* param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function used to handle window resizing.
|
||||||
|
*
|
||||||
|
* WARNING: The function is called every frame during which the window is being
|
||||||
|
* resized, be aware!
|
||||||
|
*
|
||||||
|
* @param[in] width The new width of the window.
|
||||||
|
* @param[in] height The new height of the window.
|
||||||
|
* @param[in] param Additional parameter to pass on to the function.
|
||||||
|
*/
|
||||||
|
typedef void (*mlx_resizefunc)(int32_t width, int32_t height, void* param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function used to handle window closing which is called when
|
||||||
|
* the user attempts to close the window, for example by clicking the
|
||||||
|
* close widget in the title bar.
|
||||||
|
*
|
||||||
|
* @param[in] param Additional parameter to pass on to the function.
|
||||||
|
*/
|
||||||
|
typedef void (*mlx_closefunc)(void* param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Typedef for a window cursor object, these eventually expand to
|
||||||
|
* the native cursor object, but are hidden from the user.
|
||||||
|
*
|
||||||
|
* Under GLFW they are named GLFWcursor and have a wrapper for each implementation.
|
||||||
|
* You can find the ACTUAL cursor in the following files at GLFW named under *_platform.h
|
||||||
|
*/
|
||||||
|
typedef void mlx_win_cursor_t;
|
||||||
|
|
||||||
|
//= Error Functions =//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the english description of the error code.
|
||||||
|
*
|
||||||
|
* @param[in] val The error code.
|
||||||
|
* @return The error string that describes the error code.
|
||||||
|
*/
|
||||||
|
const char* mlx_strerror(mlx_errno_t val);
|
||||||
|
|
||||||
|
//= Generic Functions =//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new MLX42 Instance.
|
||||||
|
*
|
||||||
|
* @param[in] width The width of the window.
|
||||||
|
* @param[in] height The height of the window.
|
||||||
|
* @param[in] title The title of the window.
|
||||||
|
* @param[in] resize Enable window resizing.
|
||||||
|
* @returns Ptr to the MLX handle or null on failure.
|
||||||
|
*/
|
||||||
|
mlx_t* mlx_init(int32_t width, int32_t height, const char* title, bool resize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a setting for MLX42.
|
||||||
|
* Settings can manipulate the core behaviour of the engine.
|
||||||
|
*
|
||||||
|
* @param[in] setting The settings value, See mlx_settings_t type.
|
||||||
|
* @param[in] value Settings value to determine the state of the setting. Can be a boolean or an enum / macro.
|
||||||
|
*/
|
||||||
|
void mlx_set_setting(mlx_settings_t setting, int32_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies MLX that it should stop rendering and exit the main loop.
|
||||||
|
* This is not the same as terminate, this simply tells MLX to close the window.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
*/
|
||||||
|
void mlx_close_window(mlx_t* mlx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the rendering of MLX, this function won't return until
|
||||||
|
* mlx_close_window is called, meaning it will loop until the user requests that
|
||||||
|
* the window should close.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
*/
|
||||||
|
void mlx_loop(mlx_t* mlx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lets you set a custom image as the program icon.
|
||||||
|
*
|
||||||
|
* NOTE: In MacOS this function does nothing, you should use the bundles icon to set the dock bar icon.
|
||||||
|
* @see: https://9to5mac.com/2021/11/08/change-mac-icons/
|
||||||
|
* @see: https://github.com/glfw/glfw/issues/2041
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] image The image to use as icon.
|
||||||
|
*/
|
||||||
|
void mlx_set_icon(mlx_t* mlx, mlx_texture_t* image);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Terminates MLX and cleans up any of its used resources.
|
||||||
|
* Using any functions that require mlx afterwards will
|
||||||
|
* be considered undefined behaviour, beware of segfaults.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
*/
|
||||||
|
void mlx_terminate(mlx_t* mlx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the elapsed time since MLX was initialized.
|
||||||
|
*
|
||||||
|
* @return The amount of time elapsed in seconds.
|
||||||
|
*/
|
||||||
|
double mlx_get_time(void);
|
||||||
|
|
||||||
|
//= Window/Monitor Functions =//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function brings the specified window to front and sets input focus.
|
||||||
|
*
|
||||||
|
* Do not use this function to steal focus from other applications unless
|
||||||
|
* you are certain that is what the user wants. Focus stealing can be
|
||||||
|
* extremely disruptive.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
*/
|
||||||
|
void mlx_focus(mlx_t* mlx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the size of the specified monitor.
|
||||||
|
*
|
||||||
|
* @param[in] index Normally 0, in case of multiple windows, can be specified
|
||||||
|
* @param[in] width The width of the window.
|
||||||
|
* @param[in] height The height of the window.
|
||||||
|
*/
|
||||||
|
void mlx_get_monitor_size(int32_t index, int32_t* width, int32_t* height);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the window's position.
|
||||||
|
*
|
||||||
|
* Do not use this function to move an already visible window unless you
|
||||||
|
* have very good reasons for doing so, as it will confuse and annoy the user.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] xpos The x position.
|
||||||
|
* @param[in] ypos The y position.
|
||||||
|
*/
|
||||||
|
void mlx_set_window_pos(mlx_t* mlx, int32_t xpos, int32_t ypos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the window's position.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[out] xpos The x position.
|
||||||
|
* @param[out] ypos The y position.
|
||||||
|
*/
|
||||||
|
void mlx_get_window_pos(mlx_t* mlx, int32_t* xpos, int32_t* ypos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the window size to the newly specified values.
|
||||||
|
* Use this to update the window width and heigth values in the mlx ptr.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] new_width The new desired width.
|
||||||
|
* @param[in] new_height The new desired height.
|
||||||
|
*/
|
||||||
|
void mlx_set_window_size(mlx_t* mlx, int32_t new_width, int32_t new_height);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the size limits of the specified window.
|
||||||
|
* Will force the window to not be resizable past or below the given values.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] min_w The min width of the window.
|
||||||
|
* @param[in] max_w The max width of the window.
|
||||||
|
* @param[in] min_h The min height of the window.
|
||||||
|
* @param[in] max_h The max height of the window.
|
||||||
|
*/
|
||||||
|
void mlx_set_window_limit(mlx_t* mlx, int32_t min_w, int32_t min_h, int32_t max_w, int32_t max_h);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the title of the window.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] title The window title.
|
||||||
|
*/
|
||||||
|
void mlx_set_window_title(mlx_t* mlx, const char* title);
|
||||||
|
|
||||||
|
//= Input Functions =//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true or false if the key is down or not.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] key The keycode to check, use MLX_KEY_... to specify!
|
||||||
|
* @returns True or false if the key is down or not.
|
||||||
|
*/
|
||||||
|
bool mlx_is_key_down(mlx_t* mlx, keys_t key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether a mouse button is pressed or not.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] key A specific mouse key. e.g MLX_MOUSE_BUTTON_0
|
||||||
|
* @returns True or false if the mouse key is down or not.
|
||||||
|
*/
|
||||||
|
bool mlx_is_mouse_down(mlx_t* mlx, mouse_key_t key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current, relative, mouse cursor position on the window, starting
|
||||||
|
* from the top left corner.
|
||||||
|
*
|
||||||
|
* Negative values or values greater than window width or height
|
||||||
|
* indicate that it is outside the window.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[out] x The position.
|
||||||
|
* @param[out] y The position.
|
||||||
|
*/
|
||||||
|
void mlx_get_mouse_pos(mlx_t* mlx, int32_t* x, int32_t* y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the mouse position.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] pos The position.
|
||||||
|
*/
|
||||||
|
void mlx_set_mouse_pos(mlx_t* mlx, int32_t x, int32_t y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the state for the cursor, which can be:
|
||||||
|
* - Normal
|
||||||
|
* - Hidden
|
||||||
|
* - Disabled
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] mode A specified mouse mode.
|
||||||
|
*/
|
||||||
|
void mlx_set_cursor_mode(mlx_t* mlx, mouse_mode_t mode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the system standard cursor.
|
||||||
|
*
|
||||||
|
* @param[in] type The standard cursor type to create.
|
||||||
|
* @return The cursor object or null on failure.
|
||||||
|
*/
|
||||||
|
mlx_win_cursor_t* mlx_create_std_cursor(cursor_t type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows for the creation of custom cursors with a given texture.
|
||||||
|
*
|
||||||
|
* Use mlx_set_cursor to select the specific cursor.
|
||||||
|
* Cursors are destroyed at mlx_terminate().
|
||||||
|
*
|
||||||
|
* @param[in] texture The texture to use as cursor.
|
||||||
|
* @returns The cursor object or null on failure.
|
||||||
|
*/
|
||||||
|
mlx_win_cursor_t* mlx_create_cursor(mlx_texture_t* texture);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys the given cursor object.
|
||||||
|
*
|
||||||
|
* @param[in] cursor The cursor object to destroy.
|
||||||
|
*/
|
||||||
|
void mlx_destroy_cursor(mlx_win_cursor_t* cursor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the current cursor to the given custom cursor.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] cursor The cursor object to display, if null default cursor is selected.
|
||||||
|
*/
|
||||||
|
void mlx_set_cursor(mlx_t* mlx, mlx_win_cursor_t* cursor);
|
||||||
|
|
||||||
|
//= Hooks =//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function sets the scroll callback, which is called when a scrolling
|
||||||
|
* device is used, such as a mouse wheel.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] func The scroll wheel callback function.
|
||||||
|
* @param[in] param An additional optional parameter.
|
||||||
|
*/
|
||||||
|
void mlx_scroll_hook(mlx_t* mlx, mlx_scrollfunc func, void* param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function sets the mouse callback, which is called when a mouse
|
||||||
|
* does any sort of action such as pressing a key.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] func The mouse callback function.
|
||||||
|
* @param[in] param An additional optional parameter.
|
||||||
|
*/
|
||||||
|
void mlx_mouse_hook(mlx_t* mlx, mlx_mousefunc func, void* param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function sets the cursor callback, which is called when the
|
||||||
|
* mouse position changes. Position is relative to the window.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] func The cursor callback function.
|
||||||
|
* @param[in] param An additional optional parameter.
|
||||||
|
*/
|
||||||
|
void mlx_cursor_hook(mlx_t* mlx, mlx_cursorfunc func, void* param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function sets the key callback, which is called when a key is pressed
|
||||||
|
* on the keyboard. Useful for single keypress detection.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] func The keypress callback function.
|
||||||
|
* @param[in] param An additional optional parameter.
|
||||||
|
*/
|
||||||
|
void mlx_key_hook(mlx_t* mlx, mlx_keyfunc func, void* param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function sets the close callback, which is called in attempt to close
|
||||||
|
* the window device such as a close window widget used in the window bar.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] func The close callback function.
|
||||||
|
* @param[in] param An additional optional parameter.
|
||||||
|
*/
|
||||||
|
void mlx_close_hook(mlx_t* mlx, mlx_closefunc func, void* param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function sets the resize callback, which is called when the window is
|
||||||
|
* resized
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] func The resize callback function.
|
||||||
|
* @param[in] param An additional optional parameter.
|
||||||
|
*/
|
||||||
|
void mlx_resize_hook(mlx_t* mlx, mlx_resizefunc func, void* param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic loop hook for any custom hooks to add to the main loop.
|
||||||
|
* Executes a function per frame, so be careful.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] f The function.
|
||||||
|
* @param[in] param The parameter to pass on to the function.
|
||||||
|
* @returns Whether or not the hook was added successfully.
|
||||||
|
*/
|
||||||
|
bool mlx_loop_hook(mlx_t* mlx, void (*f)(void*), void* param);
|
||||||
|
|
||||||
|
//= Texture Functions =//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode/load a PNG file into a buffer.
|
||||||
|
*
|
||||||
|
* @param[in] path Path to the PNG file.
|
||||||
|
* @return If successful the texture data is returned, else NULL.
|
||||||
|
*/
|
||||||
|
mlx_texture_t* mlx_load_png(const char* path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads an XPM42 texture from the given file path.
|
||||||
|
*
|
||||||
|
* @param[in] path The file path to the XPM texture.
|
||||||
|
* @returns The XPM texture struct containing its information.
|
||||||
|
*/
|
||||||
|
xpm_t* mlx_load_xpm42(const char* path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a texture by freeing its allocated data.
|
||||||
|
*
|
||||||
|
* @param[in] texture The texture to free.
|
||||||
|
*/
|
||||||
|
void mlx_delete_texture(mlx_texture_t* texture);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes an XPM42 texture by freeing its allocated data.
|
||||||
|
*
|
||||||
|
* This will not remove any already drawn XPMs, it simply
|
||||||
|
* deletes the XPM buffer.
|
||||||
|
*
|
||||||
|
* @param[in] xpm The xpm texture to delete.
|
||||||
|
*/
|
||||||
|
void mlx_delete_xpm42(xpm_t* xpm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a given texture to an image.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] texture The texture to use to create the image from.
|
||||||
|
* @return mlx_image_t* The image created from the texture.
|
||||||
|
*/
|
||||||
|
mlx_image_t* mlx_texture_to_image(mlx_t* mlx, mlx_texture_t* texture);
|
||||||
|
|
||||||
|
//= Image Functions =//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets / puts a pixel onto an image.
|
||||||
|
*
|
||||||
|
* NOTE: It is considered undefined behaviour when putting a pixel
|
||||||
|
* beyond the bounds of an image.
|
||||||
|
*
|
||||||
|
* @param[in] image The MLX instance handle.
|
||||||
|
* @param[in] x The X coordinate position.
|
||||||
|
* @param[in] y The Y coordinate position.
|
||||||
|
* @param[in] color The color value to put.
|
||||||
|
*/
|
||||||
|
void mlx_put_pixel(mlx_image_t* image, uint32_t x, uint32_t y, uint32_t color);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and allocates a new image buffer.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] width The desired width of the image.
|
||||||
|
* @param[in] height The desired height of the image.
|
||||||
|
* @return Pointer to the image buffer, if it failed to allocate then NULL.
|
||||||
|
*/
|
||||||
|
mlx_image_t* mlx_new_image(mlx_t* mlx, uint32_t width, uint32_t height);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws a new instance of an image, it will then share the same
|
||||||
|
* pixel buffer as the image.
|
||||||
|
*
|
||||||
|
* NOTE: Keep in mind that the instance array gets reallocated, try
|
||||||
|
* to store the return value to the instance!
|
||||||
|
* NOT the pointer! It will become invalid!
|
||||||
|
*
|
||||||
|
* WARNING: Try to display as few images on the window as possible,
|
||||||
|
* drawing too many images will cause a loss in peformance!
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] img The image to draw on the screen.
|
||||||
|
* @param[in] x The X position.
|
||||||
|
* @param[in] y The Y position.
|
||||||
|
* @return Index to the instance, or -1 on failure.
|
||||||
|
*/
|
||||||
|
int32_t mlx_image_to_window(mlx_t* mlx, mlx_image_t* img, int32_t x, int32_t y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deleting an image will remove it from the render queue as well as any and all
|
||||||
|
* instances it might have. Additionally, just as extra measures sets all the
|
||||||
|
* data to NULL.
|
||||||
|
*
|
||||||
|
* If you simply wish to stop rendering an image without de-allocation
|
||||||
|
* set the 'enabled' boolean in the image struct.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] image The image to delete.
|
||||||
|
*/
|
||||||
|
void mlx_delete_image(mlx_t* mlx, mlx_image_t* image);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows you to resize an image, a new pixel buffer is allocated
|
||||||
|
* to fit & the previous data is scaled to fit the new size.
|
||||||
|
*
|
||||||
|
* @param[in] img The image to resize.
|
||||||
|
* @param[in] nwidth The new width.
|
||||||
|
* @param[in] nheight The new height.
|
||||||
|
* @return True if image was resized or false on error.
|
||||||
|
*/
|
||||||
|
bool mlx_resize_image(mlx_image_t* img, uint32_t nwidth, uint32_t nheight);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the depth / Z axis value of an instance.
|
||||||
|
*
|
||||||
|
* NOTE: Keep in mind that images that are on the same Z layer cut each other off.
|
||||||
|
* so if you don't see your image anymore make sure it's not conflicting by being on
|
||||||
|
* the same layer as another image.
|
||||||
|
*
|
||||||
|
* @param[in] instance The instance on which to change the depth.
|
||||||
|
* @param[in] zdepth The new depth value.
|
||||||
|
*/
|
||||||
|
void mlx_set_instance_depth(mlx_instance_t* instance, int32_t zdepth);
|
||||||
|
|
||||||
|
//= String Functions =//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws a string on an image and then outputs it to the window.
|
||||||
|
*
|
||||||
|
* @param[in] mlx The MLX instance handle.
|
||||||
|
* @param[in] str The string to draw.
|
||||||
|
* @param[in] x The X location.
|
||||||
|
* @param[in] y The Y location.
|
||||||
|
* @return Image ptr to the string.
|
||||||
|
*/
|
||||||
|
mlx_image_t* mlx_put_string(mlx_t* mlx, const char* str, int32_t x, int32_t y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the texture data for the built-in font.
|
||||||
|
*
|
||||||
|
* @return Pointer to the built-in font texture.
|
||||||
|
*/
|
||||||
|
const mlx_texture_t* mlx_get_font(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function lets you retrieve the X offset
|
||||||
|
* of the given char in the font texture.
|
||||||
|
*
|
||||||
|
* NOTE: A single character is 10 * 20 in pixels!
|
||||||
|
*
|
||||||
|
* @param[in] c The character to get the offset from.
|
||||||
|
* @return Non-negative if found or -1 if not found.
|
||||||
|
*/
|
||||||
|
int32_t mlx_get_texoffset(char c);
|
||||||
|
|
||||||
|
# ifdef __cplusplus
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
#endif
|
231
MLX42/include/MLX42/MLX42_Input.h
Normal file
231
MLX42/include/MLX42/MLX42_Input.h
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* :::::::: */
|
||||||
|
/* MLX42_Keys.h :+: :+: */
|
||||||
|
/* +:+ */
|
||||||
|
/* By: W2Wizard <w2.wizzard@gmail.com> +#+ */
|
||||||
|
/* +#+ */
|
||||||
|
/* Created: 2021/12/28 02:29:06 by W2Wizard #+# #+# */
|
||||||
|
/* Updated: 2022/03/02 16:48:27 by lde-la-h ######## odam.nl */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These are copied from GLFW.
|
||||||
|
*
|
||||||
|
* Any new entries should have the exact same values as defined
|
||||||
|
* over in the glfw3.h file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MLX42_INPUT_H
|
||||||
|
# define MLX42_INPUT_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A key action such as pressing or releasing a key.
|
||||||
|
*
|
||||||
|
* @param RELEASE Execute when the key is being released.
|
||||||
|
* @param PRESS Execute when the key is being pressed.
|
||||||
|
* @param REPEAT Execute when the key is being held down.
|
||||||
|
*/
|
||||||
|
typedef enum action
|
||||||
|
{
|
||||||
|
MLX_RELEASE = 0,
|
||||||
|
MLX_PRESS = 1,
|
||||||
|
MLX_REPEAT = 2,
|
||||||
|
} action_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key modifiers, such as shift, control or alt.
|
||||||
|
* These keys are flags meaning you can combine them to detect
|
||||||
|
* key combinations such as CTRL + ALT so CTRL | ALT.
|
||||||
|
*
|
||||||
|
* @param SHIFT The shift key.
|
||||||
|
* @param CONTROL The control key.
|
||||||
|
* @param ALT The alt key.
|
||||||
|
* @param SUPERKEY The Superkey such as the Windows Key or Command.
|
||||||
|
* @param CAPSLOCK The capslock key.
|
||||||
|
* @param NUMLOCK The numlock key.
|
||||||
|
*/
|
||||||
|
typedef enum modifier_key
|
||||||
|
{
|
||||||
|
MLX_SHIFT = 0x0001,
|
||||||
|
MLX_CONTROL = 0x0002,
|
||||||
|
MLX_ALT = 0x0004,
|
||||||
|
MLX_SUPERKEY = 0x0008,
|
||||||
|
MLX_CAPSLOCK = 0x0010,
|
||||||
|
MLX_NUMLOCK = 0x0020,
|
||||||
|
} modifier_key_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mouse button keycodes.
|
||||||
|
* @param LEFT The left mouse button.
|
||||||
|
* @param RIGHT The right mouse button.
|
||||||
|
* @param MIDDLE The middle mouse button, aka the Scrollwheel.
|
||||||
|
*/
|
||||||
|
typedef enum mouse_key
|
||||||
|
{
|
||||||
|
MLX_MOUSE_BUTTON_LEFT = 0,
|
||||||
|
MLX_MOUSE_BUTTON_RIGHT = 1,
|
||||||
|
MLX_MOUSE_BUTTON_MIDDLE = 2,
|
||||||
|
} mouse_key_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Various mouse/cursor states.
|
||||||
|
* @param NORMAL Simple visible default cursor.
|
||||||
|
* @param HIDDEN The cursor is not rendered but still functions.
|
||||||
|
* @param DISABLED The cursor is not rendered, nor is it functional.
|
||||||
|
*/
|
||||||
|
typedef enum mouse_mode
|
||||||
|
{
|
||||||
|
MLX_MOUSE_NORMAL = 0x00034001,
|
||||||
|
MLX_MOUSE_HIDDEN = 0x00034002,
|
||||||
|
MLX_MOUSE_DISABLED = 0x00034003,
|
||||||
|
} mouse_mode_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Various cursors that are standard.
|
||||||
|
* @param ARROW The regular arrow cursor.
|
||||||
|
* @param IBEAM The text input I-beam cursor shape.
|
||||||
|
* @param CROSSHAIR The crosshair shape cursor.
|
||||||
|
* @param HAND The hand shape cursor.
|
||||||
|
* @param HRESIZE The horizontal resize arrow shape.
|
||||||
|
* @param VRESIZE The vertical resize arrow shape.
|
||||||
|
*/
|
||||||
|
typedef enum cursor
|
||||||
|
{
|
||||||
|
MLX_CURSOR_ARROW = 0x00036001,
|
||||||
|
MLX_CURSOR_IBEAM = 0x00036002,
|
||||||
|
MLX_CURSOR_CROSSHAIR = 0x00036003,
|
||||||
|
MLX_CURSOR_HAND = 0x00036004,
|
||||||
|
MLX_CURSOR_HRESIZE = 0x00036005,
|
||||||
|
MLX_CURSOR_VRESIZE = 0x00036006,
|
||||||
|
} cursor_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All sorts of keyboard keycodes.
|
||||||
|
*
|
||||||
|
* KP = Keypad.
|
||||||
|
*/
|
||||||
|
typedef enum keys
|
||||||
|
{
|
||||||
|
MLX_KEY_SPACE = 32,
|
||||||
|
MLX_KEY_APOSTROPHE = 39,
|
||||||
|
MLX_KEY_COMMA = 44,
|
||||||
|
MLX_KEY_MINUS = 45,
|
||||||
|
MLX_KEY_PERIOD = 46,
|
||||||
|
MLX_KEY_SLASH = 47,
|
||||||
|
MLX_KEY_0 = 48,
|
||||||
|
MLX_KEY_1 = 49,
|
||||||
|
MLX_KEY_2 = 50,
|
||||||
|
MLX_KEY_3 = 51,
|
||||||
|
MLX_KEY_4 = 52,
|
||||||
|
MLX_KEY_5 = 53,
|
||||||
|
MLX_KEY_6 = 54,
|
||||||
|
MLX_KEY_7 = 55,
|
||||||
|
MLX_KEY_8 = 56,
|
||||||
|
MLX_KEY_9 = 57,
|
||||||
|
MLX_KEY_SEMICOLON = 59,
|
||||||
|
MLX_KEY_EQUAL = 61,
|
||||||
|
MLX_KEY_A = 65,
|
||||||
|
MLX_KEY_B = 66,
|
||||||
|
MLX_KEY_C = 67,
|
||||||
|
MLX_KEY_D = 68,
|
||||||
|
MLX_KEY_E = 69,
|
||||||
|
MLX_KEY_F = 70,
|
||||||
|
MLX_KEY_G = 71,
|
||||||
|
MLX_KEY_H = 72,
|
||||||
|
MLX_KEY_I = 73,
|
||||||
|
MLX_KEY_J = 74,
|
||||||
|
MLX_KEY_K = 75,
|
||||||
|
MLX_KEY_L = 76,
|
||||||
|
MLX_KEY_M = 77,
|
||||||
|
MLX_KEY_N = 78,
|
||||||
|
MLX_KEY_O = 79,
|
||||||
|
MLX_KEY_P = 80,
|
||||||
|
MLX_KEY_Q = 81,
|
||||||
|
MLX_KEY_R = 82,
|
||||||
|
MLX_KEY_S = 83,
|
||||||
|
MLX_KEY_T = 84,
|
||||||
|
MLX_KEY_U = 85,
|
||||||
|
MLX_KEY_V = 86,
|
||||||
|
MLX_KEY_W = 87,
|
||||||
|
MLX_KEY_X = 88,
|
||||||
|
MLX_KEY_Y = 89,
|
||||||
|
MLX_KEY_Z = 90,
|
||||||
|
MLX_KEY_LEFT_BRACKET = 91,
|
||||||
|
MLX_KEY_BACKSLASH = 92,
|
||||||
|
MLX_KEY_RIGHT_BRACKET = 93,
|
||||||
|
MLX_KEY_GRAVE_ACCENT = 96,
|
||||||
|
MLX_KEY_ESCAPE = 256,
|
||||||
|
MLX_KEY_ENTER = 257,
|
||||||
|
MLX_KEY_TAB = 258,
|
||||||
|
MLX_KEY_BACKSPACE = 259,
|
||||||
|
MLX_KEY_INSERT = 260,
|
||||||
|
MLX_KEY_DELETE = 261,
|
||||||
|
MLX_KEY_RIGHT = 262,
|
||||||
|
MLX_KEY_LEFT = 263,
|
||||||
|
MLX_KEY_DOWN = 264,
|
||||||
|
MLX_KEY_UP = 265,
|
||||||
|
MLX_KEY_PAGE_UP = 266,
|
||||||
|
MLX_KEY_PAGE_DOWN = 267,
|
||||||
|
MLX_KEY_HOME = 268,
|
||||||
|
MLX_KEY_END = 269,
|
||||||
|
MLX_KEY_CAPS_LOCK = 280,
|
||||||
|
MLX_KEY_SCROLL_LOCK = 281,
|
||||||
|
MLX_KEY_NUM_LOCK = 282,
|
||||||
|
MLX_KEY_PRINT_SCREEN = 283,
|
||||||
|
MLX_KEY_PAUSE = 284,
|
||||||
|
MLX_KEY_F1 = 290,
|
||||||
|
MLX_KEY_F2 = 291,
|
||||||
|
MLX_KEY_F3 = 292,
|
||||||
|
MLX_KEY_F4 = 293,
|
||||||
|
MLX_KEY_F5 = 294,
|
||||||
|
MLX_KEY_F6 = 295,
|
||||||
|
MLX_KEY_F7 = 296,
|
||||||
|
MLX_KEY_F8 = 297,
|
||||||
|
MLX_KEY_F9 = 298,
|
||||||
|
MLX_KEY_F10 = 299,
|
||||||
|
MLX_KEY_F11 = 300,
|
||||||
|
MLX_KEY_F12 = 301,
|
||||||
|
MLX_KEY_F13 = 302,
|
||||||
|
MLX_KEY_F14 = 303,
|
||||||
|
MLX_KEY_F15 = 304,
|
||||||
|
MLX_KEY_F16 = 305,
|
||||||
|
MLX_KEY_F17 = 306,
|
||||||
|
MLX_KEY_F18 = 307,
|
||||||
|
MLX_KEY_F19 = 308,
|
||||||
|
MLX_KEY_F20 = 309,
|
||||||
|
MLX_KEY_F21 = 310,
|
||||||
|
MLX_KEY_F22 = 311,
|
||||||
|
MLX_KEY_F23 = 312,
|
||||||
|
MLX_KEY_F24 = 313,
|
||||||
|
MLX_KEY_F25 = 314,
|
||||||
|
MLX_KEY_KP_0 = 320,
|
||||||
|
MLX_KEY_KP_1 = 321,
|
||||||
|
MLX_KEY_KP_2 = 322,
|
||||||
|
MLX_KEY_KP_3 = 323,
|
||||||
|
MLX_KEY_KP_4 = 324,
|
||||||
|
MLX_KEY_KP_5 = 325,
|
||||||
|
MLX_KEY_KP_6 = 326,
|
||||||
|
MLX_KEY_KP_7 = 327,
|
||||||
|
MLX_KEY_KP_8 = 328,
|
||||||
|
MLX_KEY_KP_9 = 329,
|
||||||
|
MLX_KEY_KP_DECIMAL = 330,
|
||||||
|
MLX_KEY_KP_DIVIDE = 331,
|
||||||
|
MLX_KEY_KP_MULTIPLY = 332,
|
||||||
|
MLX_KEY_KP_SUBTRACT = 333,
|
||||||
|
MLX_KEY_KP_ADD = 334,
|
||||||
|
MLX_KEY_KP_ENTER = 335,
|
||||||
|
MLX_KEY_KP_EQUAL = 336,
|
||||||
|
MLX_KEY_LEFT_SHIFT = 340,
|
||||||
|
MLX_KEY_LEFT_CONTROL = 341,
|
||||||
|
MLX_KEY_LEFT_ALT = 342,
|
||||||
|
MLX_KEY_LEFT_SUPER = 343,
|
||||||
|
MLX_KEY_RIGHT_SHIFT = 344,
|
||||||
|
MLX_KEY_RIGHT_CONTROL = 345,
|
||||||
|
MLX_KEY_RIGHT_ALT = 346,
|
||||||
|
MLX_KEY_RIGHT_SUPER = 347,
|
||||||
|
MLX_KEY_MENU = 348,
|
||||||
|
} keys_t;
|
||||||
|
|
||||||
|
#endif
|
252
MLX42/include/MLX42/MLX42_Int.h
Normal file
252
MLX42/include/MLX42/MLX42_Int.h
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* :::::::: */
|
||||||
|
/* MLX42_Int.h :+: :+: */
|
||||||
|
/* +:+ */
|
||||||
|
/* By: W2Wizard <w2.wizzard@gmail.com> +#+ */
|
||||||
|
/* +#+ */
|
||||||
|
/* Created: 2021/12/27 23:55:34 by W2Wizard #+# #+# */
|
||||||
|
/* Updated: 2022/07/21 10:46:43 by sbos ######## odam.nl */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#ifndef MLX42_INT_H
|
||||||
|
# define MLX42_INT_H
|
||||||
|
# define LODEPNG_NO_COMPILE_ALLOCATORS
|
||||||
|
# include "MLX42/MLX42.h"
|
||||||
|
# include "lodepng/lodepng.h"
|
||||||
|
# include "glad/glad.h"
|
||||||
|
# include "KHR/khrplatform.h"
|
||||||
|
# if defined(__APPLE__)
|
||||||
|
# define GL_SILENCE_DEPRECATION
|
||||||
|
# endif
|
||||||
|
# include <GLFW/glfw3.h>
|
||||||
|
# include <stdlib.h>
|
||||||
|
# include <memory.h>
|
||||||
|
# include <stdio.h>
|
||||||
|
# if defined(__linux__)
|
||||||
|
# include <linux/limits.h>
|
||||||
|
# else
|
||||||
|
# include <limits.h>
|
||||||
|
# endif
|
||||||
|
# include <ctype.h> /* isspace, isprint, ... */
|
||||||
|
# include <string.h> /* strlen, memmove, ... */
|
||||||
|
# include <stdarg.h> /* va_arg, va_end, ... */
|
||||||
|
# include <assert.h> /* assert, static_assert, ... */
|
||||||
|
# ifndef MLX_SWAP_INTERVAL
|
||||||
|
# define MLX_SWAP_INTERVAL 1
|
||||||
|
# endif
|
||||||
|
# ifndef MLX_BATCH_SIZE
|
||||||
|
# define MLX_BATCH_SIZE 12000
|
||||||
|
# endif
|
||||||
|
# define BPP sizeof(int32_t) /* Only support RGBA */
|
||||||
|
# define GETLINE_BUFF 1280
|
||||||
|
# define MLX_MAX_STRING 512 /* Arbitrary string limit */
|
||||||
|
# define MLX_ASSERT(cond, msg) assert(cond && msg);
|
||||||
|
# define MLX_NONNULL(var) MLX_ASSERT(var, "Value can't be null"); /* Assert instead of attribute */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The shader code is extracted from the shader files
|
||||||
|
* and converted to a .c file as a single string at
|
||||||
|
* compile time. This keeps shader files external but
|
||||||
|
* still integrated into the program letting you use
|
||||||
|
* the executable anywhere without having to take the
|
||||||
|
* shaders with you.
|
||||||
|
*
|
||||||
|
* Most modern frameworks like .NET do this by having resource files
|
||||||
|
* instead.
|
||||||
|
*
|
||||||
|
* See: https://bit.ly/3LJYG0r
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern const char* vert_shader;
|
||||||
|
extern const char* frag_shader;
|
||||||
|
|
||||||
|
// Flag to indicate if the render queue has to be sorted.
|
||||||
|
extern bool sort_queue;
|
||||||
|
|
||||||
|
// Settings array, use the enum 'key' to get the value.
|
||||||
|
extern int32_t mlx_settings[MLX_SETTINGS_MAX];
|
||||||
|
|
||||||
|
//= Types =//
|
||||||
|
|
||||||
|
// A single vertex, identical to the layout in the shader.
|
||||||
|
typedef struct vertex
|
||||||
|
{
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
float u;
|
||||||
|
float v;
|
||||||
|
int8_t tex;
|
||||||
|
} vertex_t;
|
||||||
|
|
||||||
|
// Layout for linked list.
|
||||||
|
typedef struct mlx_list
|
||||||
|
{
|
||||||
|
void* content;
|
||||||
|
struct mlx_list* next;
|
||||||
|
struct mlx_list* prev;
|
||||||
|
} mlx_list_t;
|
||||||
|
|
||||||
|
//= Hook structs =//
|
||||||
|
/**
|
||||||
|
* There are 2 types of hooks, special and generics.
|
||||||
|
*
|
||||||
|
* Specials: Specials are specific callback functions to a specific action
|
||||||
|
* such as window resizing or key presses. These are attached to the
|
||||||
|
* callbacks of glfw. In case MLX itself needs the callback we call
|
||||||
|
* the specials in that callback since there can only ever be a single
|
||||||
|
* callback.
|
||||||
|
*
|
||||||
|
* Generics: Generics are MLX42 specific hooks and can have multiple
|
||||||
|
* hooks at the same time, these are executed every frame and can be
|
||||||
|
* used as an alternative for keypresses or animations for instance.
|
||||||
|
*
|
||||||
|
* NOTE: Hooks could be achieved with va_args to have any amount
|
||||||
|
* of args sized functor but we can't/don't want to let the user
|
||||||
|
* deal with va_args and having to look up what args are what, etc...
|
||||||
|
*
|
||||||
|
* We want to keep it straightforward with functors already describing
|
||||||
|
* what params they have.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct mlx_srcoll
|
||||||
|
{
|
||||||
|
void* param;
|
||||||
|
mlx_scrollfunc func;
|
||||||
|
} mlx_scroll_t;
|
||||||
|
|
||||||
|
typedef struct mlx_mouse
|
||||||
|
{
|
||||||
|
void* param;
|
||||||
|
mlx_mousefunc func;
|
||||||
|
} mlx_mouse_t;
|
||||||
|
|
||||||
|
typedef struct mlx_cursor
|
||||||
|
{
|
||||||
|
void* param;
|
||||||
|
mlx_cursorfunc func;
|
||||||
|
} mlx_cursor_t;
|
||||||
|
|
||||||
|
typedef struct mlx_close
|
||||||
|
{
|
||||||
|
void* param;
|
||||||
|
mlx_closefunc func;
|
||||||
|
} mlx_close_t;
|
||||||
|
|
||||||
|
typedef struct mlx_resize
|
||||||
|
{
|
||||||
|
void* param;
|
||||||
|
mlx_resizefunc func;
|
||||||
|
} mlx_resize_t;
|
||||||
|
|
||||||
|
typedef struct mlx_key
|
||||||
|
{
|
||||||
|
void* param;
|
||||||
|
mlx_keyfunc func;
|
||||||
|
} mlx_key_t;
|
||||||
|
|
||||||
|
typedef struct mlx_hook
|
||||||
|
{
|
||||||
|
void* param;
|
||||||
|
void (*func)(void*);
|
||||||
|
} mlx_hook_t;
|
||||||
|
|
||||||
|
//= Rendering =//
|
||||||
|
/**
|
||||||
|
* For rendering we need to store most of OpenGL's stuff
|
||||||
|
* such as the vertex array object, vertex buffer object &
|
||||||
|
* the shader program as well as hooks and the zdepth level.
|
||||||
|
*
|
||||||
|
* Additionally we represent draw calls with a linked list
|
||||||
|
* queue that points to the image and the index of its instance.
|
||||||
|
* Again, instances only carry XYZ data, so coupled with the image it
|
||||||
|
* lets us know where to draw a copy of the image.
|
||||||
|
*
|
||||||
|
* Texture contexts are kept in a struct alongside the capacity
|
||||||
|
* of the array of instances, since the array is realloced like a vector.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// MLX instance context.
|
||||||
|
typedef struct mlx_ctx
|
||||||
|
{
|
||||||
|
GLuint vao;
|
||||||
|
GLuint vbo;
|
||||||
|
GLuint shaderprogram;
|
||||||
|
|
||||||
|
uint32_t initialWidth;
|
||||||
|
uint32_t initialHeight;
|
||||||
|
|
||||||
|
mlx_list_t* hooks;
|
||||||
|
mlx_list_t* images;
|
||||||
|
mlx_list_t* render_queue;
|
||||||
|
|
||||||
|
mlx_scroll_t scroll_hook;
|
||||||
|
mlx_mouse_t mouse_hook;
|
||||||
|
mlx_cursor_t cursor_hook;
|
||||||
|
mlx_key_t key_hook;
|
||||||
|
mlx_resize_t resize_hook;
|
||||||
|
mlx_close_t close_hook;
|
||||||
|
|
||||||
|
int32_t zdepth;
|
||||||
|
int32_t bound_textures[16];
|
||||||
|
int32_t batch_size;
|
||||||
|
vertex_t batch_vertices[MLX_BATCH_SIZE];
|
||||||
|
} mlx_ctx_t;
|
||||||
|
|
||||||
|
// Draw call queue entry.
|
||||||
|
typedef struct draw_queue
|
||||||
|
{
|
||||||
|
mlx_image_t* image;
|
||||||
|
int32_t instanceid;
|
||||||
|
} draw_queue_t;
|
||||||
|
|
||||||
|
// Image context.
|
||||||
|
typedef struct mlx_image_ctx
|
||||||
|
{
|
||||||
|
GLuint texture;
|
||||||
|
size_t instances_capacity;
|
||||||
|
} mlx_image_ctx_t;
|
||||||
|
|
||||||
|
//= Functions =//
|
||||||
|
/**
|
||||||
|
* All sorts of internal functions shared in the library that
|
||||||
|
* should not be accessible to the user! No touch!
|
||||||
|
*/
|
||||||
|
|
||||||
|
//= Linked List Functions =//
|
||||||
|
|
||||||
|
mlx_list_t* mlx_lstnew(void* content);
|
||||||
|
mlx_list_t* mlx_lstlast(mlx_list_t* lst);
|
||||||
|
int32_t mlx_lstsize(mlx_list_t* lst);
|
||||||
|
void mlx_lstclear(mlx_list_t** lst, void (*del)(void*));
|
||||||
|
void mlx_lstadd_back(mlx_list_t** lst, mlx_list_t* new);
|
||||||
|
void mlx_lstadd_front(mlx_list_t** lst, mlx_list_t* new);
|
||||||
|
mlx_list_t* mlx_lstremove(mlx_list_t** lst, void* value, bool (*comp)(void*, void*));
|
||||||
|
void mlx_sort_renderqueue(mlx_list_t** lst);
|
||||||
|
|
||||||
|
//= Misc functions =//
|
||||||
|
|
||||||
|
bool mlx_equal_image(void* lstcontent, void* value);
|
||||||
|
bool mlx_equal_inst(void* lstcontent, void* value);
|
||||||
|
void mlx_draw_pixel(uint8_t* pixel, uint32_t color);
|
||||||
|
|
||||||
|
//= Error/log Handling Functions =//
|
||||||
|
|
||||||
|
bool mlx_error(mlx_errno_t val);
|
||||||
|
bool mlx_freen(int32_t count, ...);
|
||||||
|
|
||||||
|
//= OpenGL Functions =//
|
||||||
|
|
||||||
|
void mlx_update_matrix(const mlx_t* mlx, int32_t width, int32_t height);
|
||||||
|
void mlx_draw_instance(mlx_ctx_t* mlx, mlx_image_t* img, mlx_instance_t* instance);
|
||||||
|
void mlx_flush_batch(mlx_ctx_t* mlx);
|
||||||
|
|
||||||
|
// Utils Functions =//
|
||||||
|
|
||||||
|
bool mlx_getline(char** out, size_t* out_size, FILE* file);
|
||||||
|
uint32_t mlx_rgba_to_mono(uint32_t color);
|
||||||
|
int32_t mlx_atoi_base(const char* str, int32_t base);
|
||||||
|
uint64_t mlx_fnv_hash(char* str, size_t len);
|
||||||
|
#endif
|
5169
MLX42/include/glad/glad.h
Normal file
5169
MLX42/include/glad/glad.h
Normal file
File diff suppressed because it is too large
Load Diff
2085
MLX42/include/lodepng/lodepng.h
Normal file
2085
MLX42/include/lodepng/lodepng.h
Normal file
File diff suppressed because it is too large
Load Diff
2532
MLX42/lib/glad/glad.c
Normal file
2532
MLX42/lib/glad/glad.c
Normal file
File diff suppressed because it is too large
Load Diff
6658
MLX42/lib/png/lodepng.c
Normal file
6658
MLX42/lib/png/lodepng.c
Normal file
File diff suppressed because it is too large
Load Diff
48
MLX42/shaders/default.frag
Normal file
48
MLX42/shaders/default.frag
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
in vec2 TexCoord;
|
||||||
|
flat in int TexIndex;
|
||||||
|
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
uniform sampler2D Texture0;
|
||||||
|
uniform sampler2D Texture1;
|
||||||
|
uniform sampler2D Texture2;
|
||||||
|
uniform sampler2D Texture3;
|
||||||
|
uniform sampler2D Texture4;
|
||||||
|
uniform sampler2D Texture5;
|
||||||
|
uniform sampler2D Texture6;
|
||||||
|
uniform sampler2D Texture7;
|
||||||
|
uniform sampler2D Texture8;
|
||||||
|
uniform sampler2D Texture9;
|
||||||
|
uniform sampler2D Texture10;
|
||||||
|
uniform sampler2D Texture11;
|
||||||
|
uniform sampler2D Texture12;
|
||||||
|
uniform sampler2D Texture13;
|
||||||
|
uniform sampler2D Texture14;
|
||||||
|
uniform sampler2D Texture15;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 outColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||||
|
switch (int(TexIndex)) {
|
||||||
|
case 0: outColor = texture(Texture0, TexCoord); break;
|
||||||
|
case 1: outColor = texture(Texture1, TexCoord); break;
|
||||||
|
case 2: outColor = texture(Texture2, TexCoord); break;
|
||||||
|
case 3: outColor = texture(Texture3, TexCoord); break;
|
||||||
|
case 4: outColor = texture(Texture4, TexCoord); break;
|
||||||
|
case 5: outColor = texture(Texture5, TexCoord); break;
|
||||||
|
case 6: outColor = texture(Texture6, TexCoord); break;
|
||||||
|
case 7: outColor = texture(Texture7, TexCoord); break;
|
||||||
|
case 8: outColor = texture(Texture8, TexCoord); break;
|
||||||
|
case 9: outColor = texture(Texture9, TexCoord); break;
|
||||||
|
case 10: outColor = texture(Texture10, TexCoord); break;
|
||||||
|
case 11: outColor = texture(Texture11, TexCoord); break;
|
||||||
|
case 12: outColor = texture(Texture12, TexCoord); break;
|
||||||
|
case 13: outColor = texture(Texture13, TexCoord); break;
|
||||||
|
case 14: outColor = texture(Texture14, TexCoord); break;
|
||||||
|
case 15: outColor = texture(Texture15, TexCoord); break;
|
||||||
|
default: outColor = vec4(1.0, 0.0, 0.0, 1.0); break;
|
||||||
|
}
|
||||||
|
FragColor = outColor;
|
||||||
|
}
|
17
MLX42/shaders/default.vert
Normal file
17
MLX42/shaders/default.vert
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 aPos;
|
||||||
|
layout(location = 1) in vec2 aTexCoord;
|
||||||
|
layout(location = 2) in int aTexIndex;
|
||||||
|
|
||||||
|
out vec2 TexCoord;
|
||||||
|
flat out int TexIndex;
|
||||||
|
|
||||||
|
uniform mat4 ProjMatrix;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = ProjMatrix * vec4(aPos, 1.0);
|
||||||
|
TexCoord = aTexCoord;
|
||||||
|
TexIndex = aTexIndex;
|
||||||
|
}
|
3543
MLX42/src/font/font.h
Normal file
3543
MLX42/src/font/font.h
Normal file
File diff suppressed because it is too large
Load Diff
80
MLX42/src/font/mlx_font.c
Normal file
80
MLX42/src/font/mlx_font.c
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* :::::::: */
|
||||||
|
/* mlx_font.c :+: :+: */
|
||||||
|
/* +:+ */
|
||||||
|
/* By: W2Wizard <w2.wizzard@gmail.com> +#+ */
|
||||||
|
/* +#+ */
|
||||||
|
/* Created: 2022/02/22 12:01:37 by W2Wizard #+# #+# */
|
||||||
|
/* Updated: 2022/06/27 19:53:36 by lde-la-h ######## odam.nl */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include "font.h"
|
||||||
|
#include "MLX42/MLX42_Int.h"
|
||||||
|
|
||||||
|
//= Private =//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the actual copying of pixels form the atlas buffer to the
|
||||||
|
* image buffer.
|
||||||
|
*
|
||||||
|
* Skips any non-printable characters.
|
||||||
|
*
|
||||||
|
* @param image The image to draw on.
|
||||||
|
* @param texture The font_atlas.
|
||||||
|
* @param texoffset The character texture X offset.
|
||||||
|
* @param imgoffset The image X offset.
|
||||||
|
*/
|
||||||
|
static void mlx_draw_char(mlx_image_t* image, int32_t texoffset, int32_t imgoffset)
|
||||||
|
{
|
||||||
|
if (texoffset < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
char* pixelx;
|
||||||
|
uint8_t* pixeli;
|
||||||
|
for (uint32_t y = 0; y < FONT_HEIGHT; y++)
|
||||||
|
{
|
||||||
|
pixelx = &font_atlas.pixels[(y * font_atlas.width + texoffset) * BPP];
|
||||||
|
pixeli = image->pixels + ((y * image->width + imgoffset) * BPP);
|
||||||
|
memcpy(pixeli, pixelx, FONT_WIDTH * BPP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//= Public =//
|
||||||
|
|
||||||
|
const mlx_texture_t* mlx_get_font(void)
|
||||||
|
{
|
||||||
|
return ((const mlx_texture_t*)&font_atlas);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t mlx_get_texoffset(char c)
|
||||||
|
{
|
||||||
|
const bool _isprint = isprint(c);
|
||||||
|
|
||||||
|
// NOTE: Cheesy branchless operation :D
|
||||||
|
// +2 To skip line separator in texture
|
||||||
|
return (-1 * !_isprint + ((FONT_WIDTH + 2) * (c - 32)) * _isprint);
|
||||||
|
}
|
||||||
|
|
||||||
|
mlx_image_t* mlx_put_string(mlx_t* mlx, const char* str, int32_t x, int32_t y)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
MLX_NONNULL(str);
|
||||||
|
|
||||||
|
mlx_image_t* strimage;
|
||||||
|
const size_t len = strlen(str);
|
||||||
|
if (len > MLX_MAX_STRING)
|
||||||
|
return ((void*)mlx_error(MLX_STRTOOBIG));
|
||||||
|
if (!(strimage = mlx_new_image(mlx, len * FONT_WIDTH, FONT_HEIGHT)))
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
// Draw the text itself
|
||||||
|
int32_t imgoffset = 0;
|
||||||
|
for (size_t i = 0; i < len; i++, imgoffset += FONT_WIDTH)
|
||||||
|
mlx_draw_char(strimage, mlx_get_texoffset(str[i]), imgoffset);
|
||||||
|
|
||||||
|
if (mlx_image_to_window(mlx, strimage, x, y) == -1)
|
||||||
|
return (mlx_delete_image(mlx, strimage), NULL);
|
||||||
|
return (strimage);
|
||||||
|
}
|
63
MLX42/src/mlx_cursor.c
Normal file
63
MLX42/src/mlx_cursor.c
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* :::::::: */
|
||||||
|
/* mlx_cursor.c :+: :+: */
|
||||||
|
/* +:+ */
|
||||||
|
/* By: W2Wizard <main@w2wizard.dev> +#+ */
|
||||||
|
/* +#+ */
|
||||||
|
/* Created: 2022/01/18 20:10:54 by W2Wizard #+# #+# */
|
||||||
|
/* Updated: 2023/03/09 11:11:45 by W2Wizard ######## odam.nl */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include "MLX42/MLX42_Int.h"
|
||||||
|
|
||||||
|
//= Public =//
|
||||||
|
|
||||||
|
mlx_win_cursor_t* mlx_create_std_cursor(cursor_t type)
|
||||||
|
{
|
||||||
|
MLX_ASSERT(type >= MLX_CURSOR_ARROW && type < MLX_CURSOR_VRESIZE, "Invalid standard cursor type");
|
||||||
|
|
||||||
|
GLFWcursor* cursor;
|
||||||
|
if ((cursor = glfwCreateStandardCursor(type)))
|
||||||
|
return (cursor);
|
||||||
|
return ((void *)mlx_error(MLX_MEMFAIL));
|
||||||
|
}
|
||||||
|
|
||||||
|
mlx_win_cursor_t* mlx_create_cursor(mlx_texture_t* texture)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(texture);
|
||||||
|
|
||||||
|
GLFWcursor* cursor;
|
||||||
|
GLFWimage image = (GLFWimage) {
|
||||||
|
.width = texture->width,
|
||||||
|
.height = texture->height,
|
||||||
|
.pixels = texture->pixels
|
||||||
|
};
|
||||||
|
|
||||||
|
if ((cursor = glfwCreateCursor(&image, 0, 0)))
|
||||||
|
return (cursor);
|
||||||
|
return ((void *)mlx_error(MLX_MEMFAIL));
|
||||||
|
}
|
||||||
|
|
||||||
|
void mlx_destroy_cursor(mlx_win_cursor_t* cursor)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(cursor);
|
||||||
|
|
||||||
|
glfwDestroyCursor(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mlx_set_cursor(mlx_t* mlx, mlx_win_cursor_t* cursor)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
MLX_NONNULL(cursor);
|
||||||
|
|
||||||
|
glfwSetCursor(mlx->window, cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mlx_set_cursor_mode(mlx_t* mlx, mouse_mode_t mode)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
|
||||||
|
glfwSetInputMode(mlx->window, GLFW_CURSOR, mode);
|
||||||
|
}
|
47
MLX42/src/mlx_exit.c
Normal file
47
MLX42/src/mlx_exit.c
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* :::::::: */
|
||||||
|
/* mlx_exit.c :+: :+: */
|
||||||
|
/* +:+ */
|
||||||
|
/* By: W2Wizard <w2.wizzard@gmail.com> +#+ */
|
||||||
|
/* +#+ */
|
||||||
|
/* Created: 2021/12/28 02:43:22 by W2Wizard #+# #+# */
|
||||||
|
/* Updated: 2022/11/26 14:23:55 by jvan-hal ######## odam.nl */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include "MLX42/MLX42_Int.h"
|
||||||
|
|
||||||
|
//= Private =//
|
||||||
|
|
||||||
|
static void mlx_free_image(void* content)
|
||||||
|
{
|
||||||
|
mlx_image_t* img = content;
|
||||||
|
|
||||||
|
mlx_freen(4, img->context, img->pixels, img->instances, img);
|
||||||
|
}
|
||||||
|
|
||||||
|
//= Public =//
|
||||||
|
|
||||||
|
void mlx_close_window(mlx_t* mlx)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
glfwSetWindowShouldClose(mlx->window, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All of glfw & glads resources are cleaned up by the terminate function.
|
||||||
|
* Now it's time to clean up our own mess.
|
||||||
|
*/
|
||||||
|
void mlx_terminate(mlx_t* mlx)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
|
||||||
|
mlx_ctx_t *const mlxctx = mlx->context;
|
||||||
|
|
||||||
|
glfwTerminate();
|
||||||
|
mlx_lstclear((mlx_list_t**)(&mlxctx->hooks), &free);
|
||||||
|
mlx_lstclear((mlx_list_t**)(&mlxctx->render_queue), &free);
|
||||||
|
mlx_lstclear((mlx_list_t**)(&mlxctx->images), &mlx_free_image);
|
||||||
|
mlx_freen(2, mlxctx, mlx);
|
||||||
|
}
|
251
MLX42/src/mlx_images.c
Normal file
251
MLX42/src/mlx_images.c
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* :::::::: */
|
||||||
|
/* mlx_images.c :+: :+: */
|
||||||
|
/* +:+ */
|
||||||
|
/* By: W2Wizard <main@w2wizard.dev> +#+ */
|
||||||
|
/* +#+ */
|
||||||
|
/* Created: 2021/12/28 02:29:06 by W2Wizard #+# #+# */
|
||||||
|
/* Updated: 2023/03/30 16:36:39 by ntamayo- ######## odam.nl */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include "MLX42/MLX42_Int.h"
|
||||||
|
|
||||||
|
//= Private =//
|
||||||
|
|
||||||
|
void mlx_flush_batch(mlx_ctx_t* mlx)
|
||||||
|
{
|
||||||
|
if (mlx->batch_size <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, mlx->vbo);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, mlx->batch_size * sizeof(vertex_t), mlx->batch_vertices, GL_STATIC_DRAW);
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, mlx->batch_size);
|
||||||
|
|
||||||
|
mlx->batch_size = 0;
|
||||||
|
memset(mlx->bound_textures, 0, sizeof(mlx->bound_textures));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int8_t mlx_bind_texture(mlx_ctx_t* mlx, mlx_image_t* img)
|
||||||
|
{
|
||||||
|
const GLint handle = (GLint)((mlx_image_ctx_t*)img->context)->texture;
|
||||||
|
|
||||||
|
// Attempt to bind the texture, or obtain the index if it is already bound.
|
||||||
|
for (int8_t i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
if (mlx->bound_textures[i] == handle)
|
||||||
|
return (i);
|
||||||
|
|
||||||
|
if (mlx->bound_textures[i] == 0)
|
||||||
|
{
|
||||||
|
mlx->bound_textures[i] = handle;
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0 + i);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, handle);
|
||||||
|
return (i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no free slot was found, flush the batch and assign the texture to the first available slot
|
||||||
|
mlx_flush_batch(mlx);
|
||||||
|
|
||||||
|
mlx->bound_textures[0] = handle;
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, handle);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal function to draw a single instance of an image
|
||||||
|
* to the screen.
|
||||||
|
*/
|
||||||
|
void mlx_draw_instance(mlx_ctx_t* mlx, mlx_image_t* img, mlx_instance_t* instance)
|
||||||
|
{
|
||||||
|
float w = (float) img->width;
|
||||||
|
float h = (float) img->height;
|
||||||
|
float x = (float) instance->x;
|
||||||
|
float y = (float) instance->y;
|
||||||
|
float z = (float) instance->z;
|
||||||
|
int8_t tex = mlx_bind_texture(mlx, img);
|
||||||
|
|
||||||
|
vertex_t vertices[6] = {
|
||||||
|
(vertex_t){x, y, z, 0.f, 0.f, tex},
|
||||||
|
(vertex_t){x + w, y + h, z, 1.f, 1.f, tex},
|
||||||
|
(vertex_t){x + w, y, z, 1.f, 0.f, tex},
|
||||||
|
(vertex_t){x, y, z, 0.f, 0.f, tex},
|
||||||
|
(vertex_t){x, y + h, z, 0.f, 1.f, tex},
|
||||||
|
(vertex_t){x + w, y + h, z, 1.f, 1.f, tex},
|
||||||
|
};
|
||||||
|
memmove(mlx->batch_vertices + mlx->batch_size, vertices, sizeof(vertices));
|
||||||
|
mlx->batch_size += 6;
|
||||||
|
|
||||||
|
if (mlx->batch_size >= MLX_BATCH_SIZE)
|
||||||
|
mlx_flush_batch(mlx);
|
||||||
|
}
|
||||||
|
|
||||||
|
mlx_instance_t* mlx_grow_instances(mlx_image_t* img, bool* did_realloc)
|
||||||
|
{
|
||||||
|
mlx_image_ctx_t* const ctx = img->context;
|
||||||
|
if (img->count >= ctx->instances_capacity)
|
||||||
|
{
|
||||||
|
if (ctx->instances_capacity == 0)
|
||||||
|
ctx->instances_capacity = img->count;
|
||||||
|
else
|
||||||
|
ctx->instances_capacity *= 2;
|
||||||
|
*did_realloc = true;
|
||||||
|
return realloc(img->instances, ctx->instances_capacity * sizeof(mlx_instance_t));
|
||||||
|
}
|
||||||
|
*did_realloc = false;
|
||||||
|
return img->instances;
|
||||||
|
}
|
||||||
|
|
||||||
|
//= Public =//
|
||||||
|
|
||||||
|
void mlx_set_instance_depth(mlx_instance_t* instance, int32_t zdepth)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(instance);
|
||||||
|
|
||||||
|
if (instance->z == zdepth)
|
||||||
|
return;
|
||||||
|
instance->z = zdepth;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NOTE: The reason why we don't sort directly is that
|
||||||
|
* the user might call this function multiple times in a row and we don't
|
||||||
|
* want to sort for every change. Pre-loop wise that is.
|
||||||
|
*/
|
||||||
|
sort_queue = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t mlx_image_to_window(mlx_t* mlx, mlx_image_t* img, int32_t x, int32_t y)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
MLX_NONNULL(img);
|
||||||
|
|
||||||
|
// Allocate buffers...
|
||||||
|
img->count++;
|
||||||
|
bool did_realloc;
|
||||||
|
mlx_instance_t* instances = mlx_grow_instances(img, &did_realloc);
|
||||||
|
draw_queue_t* queue = calloc(1, sizeof(draw_queue_t));
|
||||||
|
if (!instances || !queue)
|
||||||
|
{
|
||||||
|
if (did_realloc)
|
||||||
|
free(instances);
|
||||||
|
return (free(queue), mlx_error(MLX_MEMFAIL), -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set data...
|
||||||
|
queue->image = img;
|
||||||
|
int32_t index = queue->instanceid = img->count - 1;
|
||||||
|
img->instances = instances;
|
||||||
|
img->instances[index].x = x;
|
||||||
|
img->instances[index].y = y;
|
||||||
|
|
||||||
|
// NOTE: We keep updating the Z for the convenience of the user.
|
||||||
|
// Always update Z depth to prevent overlapping images by default.
|
||||||
|
img->instances[index].z = ((mlx_ctx_t*)mlx->context)->zdepth++;
|
||||||
|
img->instances[index].enabled = true;
|
||||||
|
|
||||||
|
// Add draw call...
|
||||||
|
sort_queue = true;
|
||||||
|
mlx_list_t* templst;
|
||||||
|
if ((templst = mlx_lstnew(queue)))
|
||||||
|
{
|
||||||
|
mlx_lstadd_front(&((mlx_ctx_t*)mlx->context)->render_queue, templst);
|
||||||
|
return (index);
|
||||||
|
}
|
||||||
|
return (mlx_freen(2, instances, queue), mlx_error(MLX_MEMFAIL), -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
mlx_image_t* mlx_new_image(mlx_t* mlx, uint32_t width, uint32_t height)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
|
||||||
|
if (!width || !height || width > INT16_MAX || height > INT16_MAX)
|
||||||
|
return ((void*)mlx_error(MLX_INVDIM));
|
||||||
|
|
||||||
|
const mlx_ctx_t* mlxctx = mlx->context;
|
||||||
|
mlx_image_t* newimg = calloc(1, sizeof(mlx_image_t));
|
||||||
|
mlx_image_ctx_t* newctx = calloc(1, sizeof(mlx_image_ctx_t));
|
||||||
|
if (!newimg || !newctx)
|
||||||
|
{
|
||||||
|
mlx_freen(2, newimg, newctx);
|
||||||
|
return ((void *)mlx_error(MLX_MEMFAIL));
|
||||||
|
}
|
||||||
|
newimg->enabled = true;
|
||||||
|
newimg->context = newctx;
|
||||||
|
(*(uint32_t*)&newimg->width) = width;
|
||||||
|
(*(uint32_t*)&newimg->height) = height;
|
||||||
|
if (!(newimg->pixels = calloc(width * height, sizeof(int32_t))))
|
||||||
|
{
|
||||||
|
mlx_freen(2, newimg, newctx);
|
||||||
|
return ((void *)mlx_error(MLX_MEMFAIL));
|
||||||
|
}
|
||||||
|
|
||||||
|
mlx_list_t* newentry;
|
||||||
|
if (!(newentry = mlx_lstnew(newimg)))
|
||||||
|
{
|
||||||
|
mlx_freen(3, newimg->pixels, newimg->context, newimg);
|
||||||
|
return ((void *)mlx_error(MLX_MEMFAIL));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate OpenGL texture
|
||||||
|
glGenTextures(1, &newctx->texture);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, newctx->texture);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
mlx_lstadd_front((mlx_list_t**)(&mlxctx->images), newentry);
|
||||||
|
return (newimg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mlx_delete_image(mlx_t* mlx, mlx_image_t* image)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
MLX_NONNULL(image);
|
||||||
|
|
||||||
|
mlx_ctx_t* mlxctx = mlx->context;
|
||||||
|
|
||||||
|
// Delete all instances in the render queue
|
||||||
|
mlx_list_t* quelst;
|
||||||
|
while ((quelst = mlx_lstremove(&mlxctx->render_queue, image, &mlx_equal_inst)))
|
||||||
|
mlx_freen(2, quelst->content, quelst);
|
||||||
|
|
||||||
|
mlx_list_t* imglst;
|
||||||
|
if ((imglst = mlx_lstremove(&mlxctx->images, image, &mlx_equal_image)))
|
||||||
|
{
|
||||||
|
glDeleteTextures(1, &((mlx_image_ctx_t*)image->context)->texture);
|
||||||
|
mlx_freen(5, image->pixels, image->instances, image->context, imglst, image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mlx_resize_image(mlx_image_t* img, uint32_t nwidth, uint32_t nheight)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(img);
|
||||||
|
|
||||||
|
if (!nwidth || !nheight || nwidth > INT16_MAX || nheight > INT16_MAX)
|
||||||
|
return (mlx_error(MLX_INVDIM));
|
||||||
|
if (nwidth != img->width || nheight != img->height)
|
||||||
|
{
|
||||||
|
uint32_t* origin = (uint32_t*)img->pixels;
|
||||||
|
float wstep = (float)img->width / nwidth;
|
||||||
|
float hstep = (float)img->height / nheight;
|
||||||
|
|
||||||
|
uint8_t* tempbuff = calloc(nwidth * nheight, BPP);
|
||||||
|
if (!tempbuff)
|
||||||
|
return (mlx_error(MLX_MEMFAIL));
|
||||||
|
img->pixels = tempbuff;
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, nwidth, nheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, img->pixels);
|
||||||
|
|
||||||
|
uint32_t* destin = (uint32_t*)img->pixels;
|
||||||
|
for (uint32_t j = 0; j < nheight; j++)
|
||||||
|
for (uint32_t i = 0; i < nwidth; i++)
|
||||||
|
destin[j * nwidth + i] = origin[(uint32_t)(j * hstep) * img->width + (uint32_t)(i * wstep)];
|
||||||
|
(*(uint32_t*)&img->width) = nwidth;
|
||||||
|
(*(uint32_t*)&img->height) = nheight;
|
||||||
|
free(origin);
|
||||||
|
}
|
||||||
|
return (true);
|
||||||
|
}
|
195
MLX42/src/mlx_init.c
Normal file
195
MLX42/src/mlx_init.c
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* :::::::: */
|
||||||
|
/* mlx_init.c :+: :+: */
|
||||||
|
/* +:+ */
|
||||||
|
/* By: W2Wizard <main@w2wizard.dev> +#+ */
|
||||||
|
/* +#+ */
|
||||||
|
/* Created: 2021/12/28 00:24:30 by W2Wizard #+# #+# */
|
||||||
|
/* Updated: 2023/02/13 11:36:27 by W2Wizard ######## odam.nl */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include "MLX42/MLX42_Int.h"
|
||||||
|
|
||||||
|
//= Private =//
|
||||||
|
|
||||||
|
static void framebuffer_callback(GLFWwindow *window, int width, int height)
|
||||||
|
{
|
||||||
|
(void)window;
|
||||||
|
glViewport(0, 0, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool mlx_create_buffers(mlx_t* mlx)
|
||||||
|
{
|
||||||
|
mlx_ctx_t* mlxctx = mlx->context;
|
||||||
|
|
||||||
|
mlxctx->zdepth = 0;
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glGenVertexArrays(1, &(mlxctx->vao));
|
||||||
|
glGenBuffers(1, &(mlxctx->vbo));
|
||||||
|
glBindVertexArray(mlxctx->vao);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, mlxctx->vbo);
|
||||||
|
|
||||||
|
// Vertex XYZ coordinates
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertex_t), NULL);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
|
||||||
|
// UV Coordinates
|
||||||
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (void *)(sizeof(float) * 3));
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
|
||||||
|
// Texture index
|
||||||
|
glVertexAttribIPointer(2, 1, GL_BYTE, sizeof(vertex_t), (void *)(sizeof(float) * 5));
|
||||||
|
glEnableVertexAttribArray(2);
|
||||||
|
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
glUniform1i(glGetUniformLocation(mlxctx->shaderprogram, "Texture0"), 0);
|
||||||
|
glUniform1i(glGetUniformLocation(mlxctx->shaderprogram, "Texture1"), 1);
|
||||||
|
glUniform1i(glGetUniformLocation(mlxctx->shaderprogram, "Texture2"), 2);
|
||||||
|
glUniform1i(glGetUniformLocation(mlxctx->shaderprogram, "Texture3"), 3);
|
||||||
|
glUniform1i(glGetUniformLocation(mlxctx->shaderprogram, "Texture4"), 4);
|
||||||
|
glUniform1i(glGetUniformLocation(mlxctx->shaderprogram, "Texture5"), 5);
|
||||||
|
glUniform1i(glGetUniformLocation(mlxctx->shaderprogram, "Texture6"), 6);
|
||||||
|
glUniform1i(glGetUniformLocation(mlxctx->shaderprogram, "Texture7"), 7);
|
||||||
|
glUniform1i(glGetUniformLocation(mlxctx->shaderprogram, "Texture8"), 8);
|
||||||
|
glUniform1i(glGetUniformLocation(mlxctx->shaderprogram, "Texture9"), 9);
|
||||||
|
glUniform1i(glGetUniformLocation(mlxctx->shaderprogram, "Texture10"), 10);
|
||||||
|
glUniform1i(glGetUniformLocation(mlxctx->shaderprogram, "Texture11"), 11);
|
||||||
|
glUniform1i(glGetUniformLocation(mlxctx->shaderprogram, "Texture12"), 12);
|
||||||
|
glUniform1i(glGetUniformLocation(mlxctx->shaderprogram, "Texture13"), 13);
|
||||||
|
glUniform1i(glGetUniformLocation(mlxctx->shaderprogram, "Texture14"), 14);
|
||||||
|
glUniform1i(glGetUniformLocation(mlxctx->shaderprogram, "Texture15"), 15);
|
||||||
|
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles the given shader source code of a given shader type.
|
||||||
|
* Returns shader object via param.
|
||||||
|
*
|
||||||
|
* @param code The shader source code.
|
||||||
|
* @param Type GL_VERTEX_SHADER, GL_FRAGMENT_SHADER, GL_GEOMETRY_SHADER, ...
|
||||||
|
* @return Non-zero on success, else 0.
|
||||||
|
*/
|
||||||
|
static uint32_t mlx_compile_shader(const char* code, int32_t type)
|
||||||
|
{
|
||||||
|
GLuint shader;
|
||||||
|
int32_t success;
|
||||||
|
char infolog[512] = {0};
|
||||||
|
|
||||||
|
if (!code || (shader = glCreateShader(type)) == 0)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
GLint len = strlen(code);
|
||||||
|
glShaderSource(shader, 1, &code, &len);
|
||||||
|
glCompileShader(shader);
|
||||||
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
glGetShaderInfoLog(shader, sizeof(infolog), NULL, infolog);
|
||||||
|
fprintf(stderr, "%s", infolog);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
return (shader);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool mlx_init_render(mlx_t* mlx)
|
||||||
|
{
|
||||||
|
uint32_t vshader = 0;
|
||||||
|
uint32_t fshader = 0;
|
||||||
|
char infolog[512] = {0};
|
||||||
|
mlx_ctx_t* mlxctx = mlx->context;
|
||||||
|
|
||||||
|
glfwMakeContextCurrent(mlx->window);
|
||||||
|
glfwSetFramebufferSizeCallback(mlx->window, framebuffer_callback);
|
||||||
|
glfwSetWindowUserPointer(mlx->window, mlx);
|
||||||
|
glfwSwapInterval(MLX_SWAP_INTERVAL);
|
||||||
|
|
||||||
|
// Load all OpenGL function pointers
|
||||||
|
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
|
||||||
|
return (mlx_error(MLX_GLADFAIL));
|
||||||
|
|
||||||
|
if (!(vshader = mlx_compile_shader(vert_shader, GL_VERTEX_SHADER)))
|
||||||
|
return (mlx_error(MLX_VERTFAIL));
|
||||||
|
if (!(fshader = mlx_compile_shader(frag_shader, GL_FRAGMENT_SHADER)))
|
||||||
|
return (mlx_error(MLX_FRAGFAIL));
|
||||||
|
if (!(mlxctx->shaderprogram = glCreateProgram()))
|
||||||
|
return (mlx_error(MLX_SHDRFAIL));
|
||||||
|
glAttachShader(mlxctx->shaderprogram, vshader);
|
||||||
|
glAttachShader(mlxctx->shaderprogram, fshader);
|
||||||
|
glLinkProgram(mlxctx->shaderprogram);
|
||||||
|
|
||||||
|
int32_t success;
|
||||||
|
glGetProgramiv(mlxctx->shaderprogram, GL_LINK_STATUS, &success);
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
glGetProgramInfoLog(mlxctx->shaderprogram, sizeof(infolog), NULL, infolog);
|
||||||
|
fprintf(stderr, "%s", infolog);
|
||||||
|
return (mlx_error(MLX_SHDRFAIL));
|
||||||
|
}
|
||||||
|
glDeleteShader(vshader);
|
||||||
|
glDeleteShader(fshader);
|
||||||
|
glUseProgram(mlxctx->shaderprogram);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 16; i++)
|
||||||
|
mlxctx->bound_textures[i] = 0;
|
||||||
|
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//= Public =//
|
||||||
|
|
||||||
|
// NOTE: https://www.glfw.org/docs/3.3/group__window.html
|
||||||
|
|
||||||
|
// Default settings
|
||||||
|
int32_t mlx_settings[MLX_SETTINGS_MAX] = {false, false, false, true, false};
|
||||||
|
mlx_errno_t mlx_errno = MLX_SUCCESS;
|
||||||
|
bool sort_queue = false;
|
||||||
|
|
||||||
|
mlx_t* mlx_init(int32_t width, int32_t height, const char* title, bool resize)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(title);
|
||||||
|
MLX_ASSERT(width > 0, "Window width must be positive");
|
||||||
|
MLX_ASSERT(height > 0, "Window height must be positive");
|
||||||
|
|
||||||
|
bool init;
|
||||||
|
mlx_t* mlx;
|
||||||
|
if (!(init = glfwInit()))
|
||||||
|
return ((void*)mlx_error(MLX_GLFWFAIL));
|
||||||
|
if (!(mlx = calloc(1, sizeof(mlx_t))))
|
||||||
|
return ((void*)mlx_error(MLX_MEMFAIL));
|
||||||
|
if (!(mlx->context = calloc(1, sizeof(mlx_ctx_t))))
|
||||||
|
return (free(mlx), (void*)mlx_error(MLX_MEMFAIL));
|
||||||
|
|
||||||
|
mlx_ctx_t* const mlxctx = mlx->context;
|
||||||
|
mlx->width = width;
|
||||||
|
mlx->height = height;
|
||||||
|
mlxctx->initialWidth = width;
|
||||||
|
mlxctx->initialHeight = height;
|
||||||
|
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||||
|
glfwWindowHint(GLFW_MAXIMIZED, mlx_settings[MLX_MAXIMIZED]);
|
||||||
|
glfwWindowHint(GLFW_DECORATED, mlx_settings[MLX_DECORATED]);
|
||||||
|
glfwWindowHint(GLFW_VISIBLE, !mlx_settings[MLX_HEADLESS]);
|
||||||
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
|
#ifdef __APPLE__
|
||||||
|
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
||||||
|
#endif
|
||||||
|
glfwWindowHint(GLFW_RESIZABLE, resize);
|
||||||
|
if (!(mlx->window = glfwCreateWindow(width, height, title, mlx_settings[MLX_FULLSCREEN] ? glfwGetPrimaryMonitor() : NULL, NULL)))
|
||||||
|
return (mlx_terminate(mlx), (void*)mlx_error(MLX_WINFAIL));
|
||||||
|
if (!mlx_init_render(mlx) || !mlx_create_buffers(mlx))
|
||||||
|
return (mlx_terminate(mlx), NULL);
|
||||||
|
return (mlx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mlx_set_setting(mlx_settings_t setting, int32_t value)
|
||||||
|
{
|
||||||
|
MLX_ASSERT(setting >= 0 && setting < MLX_SETTINGS_MAX, "Invalid settings value");
|
||||||
|
mlx_settings[setting] = value;
|
||||||
|
}
|
49
MLX42/src/mlx_keys.c
Normal file
49
MLX42/src/mlx_keys.c
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* :::::::: */
|
||||||
|
/* mlx_keys.c :+: :+: */
|
||||||
|
/* +:+ */
|
||||||
|
/* By: W2Wizard <main@w2wizard.dev> +#+ */
|
||||||
|
/* +#+ */
|
||||||
|
/* Created: 2022/01/01 21:06:45 by W2Wizard #+# #+# */
|
||||||
|
/* Updated: 2023/02/13 12:24:40 by W2Wizard ######## odam.nl */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include "MLX42/MLX42_Int.h"
|
||||||
|
|
||||||
|
//= Private =//
|
||||||
|
|
||||||
|
static void mlx_key_callback(GLFWwindow* window, int32_t key, int32_t scancode, int32_t action, int32_t mods)
|
||||||
|
{
|
||||||
|
const mlx_t* mlx = glfwGetWindowUserPointer(window);
|
||||||
|
const mlx_key_t key_hook = ((mlx_ctx_t*)mlx->context)->key_hook;
|
||||||
|
const mlx_key_data_t callback_data = {
|
||||||
|
key,
|
||||||
|
action,
|
||||||
|
scancode,
|
||||||
|
mods,
|
||||||
|
};
|
||||||
|
|
||||||
|
key_hook.func(callback_data, key_hook.param);
|
||||||
|
}
|
||||||
|
|
||||||
|
//= Public =//
|
||||||
|
|
||||||
|
void mlx_key_hook(mlx_t* mlx, mlx_keyfunc func, void* param)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
MLX_NONNULL(func);
|
||||||
|
|
||||||
|
mlx_ctx_t* mlxctx = mlx->context;
|
||||||
|
mlxctx->key_hook.func = func;
|
||||||
|
mlxctx->key_hook.param = param;
|
||||||
|
glfwSetKeyCallback(mlx->window, mlx_key_callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mlx_is_key_down(mlx_t* mlx, keys_t key)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
|
||||||
|
return (glfwGetKey(mlx->window, key) == GLFW_PRESS);
|
||||||
|
}
|
118
MLX42/src/mlx_loop.c
Normal file
118
MLX42/src/mlx_loop.c
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* :::::::: */
|
||||||
|
/* mlx_loop.c :+: :+: */
|
||||||
|
/* +:+ */
|
||||||
|
/* By: W2Wizard <main@w2wizard.dev> +#+ */
|
||||||
|
/* +#+ */
|
||||||
|
/* Created: 2021/12/28 01:24:36 by W2Wizard #+# #+# */
|
||||||
|
/* Updated: 2023/03/28 16:34:17 by W2Wizard ######## odam.nl */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include "MLX42/MLX42_Int.h"
|
||||||
|
|
||||||
|
//= Private =//
|
||||||
|
|
||||||
|
static void mlx_exec_loop_hooks(mlx_t* mlx)
|
||||||
|
{
|
||||||
|
const mlx_ctx_t* mlxctx = mlx->context;
|
||||||
|
|
||||||
|
mlx_list_t* lstcpy = mlxctx->hooks;
|
||||||
|
while (lstcpy && !glfwWindowShouldClose(mlx->window))
|
||||||
|
{
|
||||||
|
mlx_hook_t* hook = ((mlx_hook_t*)lstcpy->content);
|
||||||
|
hook->func(hook->param);
|
||||||
|
lstcpy = lstcpy->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mlx_render_images(mlx_t* mlx)
|
||||||
|
{
|
||||||
|
mlx_ctx_t* mlxctx = mlx->context;
|
||||||
|
mlx_list_t* imglst = mlxctx->images;
|
||||||
|
|
||||||
|
if (sort_queue)
|
||||||
|
{
|
||||||
|
sort_queue = false;
|
||||||
|
mlx_sort_renderqueue(&mlxctx->render_queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upload image textures to GPU
|
||||||
|
while (imglst)
|
||||||
|
{
|
||||||
|
mlx_image_t* image;
|
||||||
|
if (!(image = imglst->content)) {
|
||||||
|
mlx_error(MLX_INVIMG);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, ((mlx_image_ctx_t*)image->context)->texture);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image->width, image->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);
|
||||||
|
imglst = imglst->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute draw calls
|
||||||
|
mlx_list_t* render_queue = mlxctx->render_queue;
|
||||||
|
while (render_queue)
|
||||||
|
{
|
||||||
|
draw_queue_t* drawcall = render_queue->content;
|
||||||
|
mlx_instance_t* instance = &drawcall->image->instances[drawcall->instanceid];
|
||||||
|
|
||||||
|
if (drawcall && drawcall->image->enabled && instance->enabled)
|
||||||
|
mlx_draw_instance(mlx->context, drawcall->image, instance);
|
||||||
|
render_queue = render_queue->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//= Public =//
|
||||||
|
|
||||||
|
bool mlx_loop_hook(mlx_t* mlx, void (*f)(void*), void* param)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
MLX_NONNULL(f);
|
||||||
|
|
||||||
|
mlx_hook_t* hook;
|
||||||
|
if (!(hook = malloc(sizeof(mlx_hook_t))))
|
||||||
|
return (mlx_error(MLX_MEMFAIL));
|
||||||
|
|
||||||
|
mlx_list_t* lst;
|
||||||
|
if (!(lst = mlx_lstnew(hook)))
|
||||||
|
{
|
||||||
|
free(hook);
|
||||||
|
return (mlx_error(MLX_MEMFAIL));
|
||||||
|
}
|
||||||
|
hook->func = f;
|
||||||
|
hook->param = param;
|
||||||
|
const mlx_ctx_t *mlxctx = mlx->context;
|
||||||
|
mlx_lstadd_back((mlx_list_t**)(&mlxctx->hooks), lst);
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||||
|
void mlx_loop(mlx_t* mlx)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
|
||||||
|
double start, oldstart = 0;
|
||||||
|
while (!glfwWindowShouldClose(mlx->window))
|
||||||
|
{
|
||||||
|
start = glfwGetTime();
|
||||||
|
mlx->delta_time = start - oldstart;
|
||||||
|
oldstart = start;
|
||||||
|
|
||||||
|
glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
glfwGetWindowSize(mlx->window, &(mlx->width), &(mlx->height));
|
||||||
|
|
||||||
|
if ((mlx->width > 1 || mlx->height > 1))
|
||||||
|
mlx_update_matrix(mlx, mlx->width, mlx->height);
|
||||||
|
|
||||||
|
mlx_exec_loop_hooks(mlx);
|
||||||
|
mlx_render_images(mlx);
|
||||||
|
mlx_flush_batch(mlx->context);
|
||||||
|
|
||||||
|
glfwSwapBuffers(mlx->window);
|
||||||
|
glfwPollEvents();
|
||||||
|
}
|
||||||
|
}
|
37
MLX42/src/mlx_monitor.c
Normal file
37
MLX42/src/mlx_monitor.c
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* :::::::: */
|
||||||
|
/* mlx_monitor.c :+: :+: */
|
||||||
|
/* +:+ */
|
||||||
|
/* By: W2Wizard <w2.wizzard@gmail.com> +#+ */
|
||||||
|
/* +#+ */
|
||||||
|
/* Created: 2022/01/19 17:18:59 by W2Wizard #+# #+# */
|
||||||
|
/* Updated: 2022/06/27 20:02:38 by lde-la-h ######## odam.nl */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include "MLX42/MLX42_Int.h"
|
||||||
|
|
||||||
|
//= Public =//
|
||||||
|
|
||||||
|
void mlx_get_monitor_size(int32_t index, int32_t* width, int32_t* height)
|
||||||
|
{
|
||||||
|
MLX_ASSERT(index >= 0, "Index out of bounds");
|
||||||
|
MLX_NONNULL(width);
|
||||||
|
MLX_NONNULL(height);
|
||||||
|
|
||||||
|
*width = 0;
|
||||||
|
*height = 0;
|
||||||
|
|
||||||
|
int32_t monitor_count;
|
||||||
|
GLFWmonitor** monitors = glfwGetMonitors(&monitor_count);
|
||||||
|
if (index > monitor_count || !monitors)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const GLFWvidmode* vidmode;
|
||||||
|
if ((vidmode = glfwGetVideoMode(monitors[index])))
|
||||||
|
{
|
||||||
|
*width = vidmode->width;
|
||||||
|
*height = vidmode->height;
|
||||||
|
}
|
||||||
|
}
|
100
MLX42/src/mlx_mouse.c
Normal file
100
MLX42/src/mlx_mouse.c
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* :::::::: */
|
||||||
|
/* mlx_mouse.c :+: :+: */
|
||||||
|
/* +:+ */
|
||||||
|
/* By: W2Wizard <w2.wizzard@gmail.com> +#+ */
|
||||||
|
/* +#+ */
|
||||||
|
/* Created: 2022/01/01 23:20:13 by W2Wizard #+# #+# */
|
||||||
|
/* Updated: 2022/06/29 15:34:25 by lde-la-h ######## odam.nl */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include "MLX42/MLX42_Int.h"
|
||||||
|
|
||||||
|
//= Private =//
|
||||||
|
|
||||||
|
static void mlx_scroll_cb(GLFWwindow* window, double xoffset, double yoffset)
|
||||||
|
{
|
||||||
|
const mlx_t* mlx = glfwGetWindowUserPointer(window);
|
||||||
|
const mlx_scroll_t scroll_hook = ((mlx_ctx_t*)mlx->context)->scroll_hook;
|
||||||
|
|
||||||
|
scroll_hook.func(xoffset, yoffset, scroll_hook.param);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mlx_mouse_cb(GLFWwindow* window, int32_t button, int32_t action, int32_t mods)
|
||||||
|
{
|
||||||
|
const mlx_t* mlx = glfwGetWindowUserPointer(window);
|
||||||
|
const mlx_mouse_t mouse_hook = ((mlx_ctx_t*)mlx->context)->mouse_hook;
|
||||||
|
|
||||||
|
mouse_hook.func(button, action, mods, mouse_hook.param);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mlx_cursor_cb(GLFWwindow* window, double xpos, double ypos)
|
||||||
|
{
|
||||||
|
const mlx_t* mlx = glfwGetWindowUserPointer(window);
|
||||||
|
const mlx_cursor_t cursor_hook = ((mlx_ctx_t*)mlx->context)->cursor_hook;
|
||||||
|
|
||||||
|
cursor_hook.func(xpos, ypos, cursor_hook.param);
|
||||||
|
}
|
||||||
|
|
||||||
|
//= Public =//
|
||||||
|
|
||||||
|
void mlx_scroll_hook(mlx_t* mlx, mlx_scrollfunc func, void* param)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
MLX_NONNULL(func);
|
||||||
|
|
||||||
|
mlx_ctx_t* const mlxctx = mlx->context;
|
||||||
|
mlxctx->scroll_hook.func = func;
|
||||||
|
mlxctx->scroll_hook.param = param;
|
||||||
|
glfwSetScrollCallback(mlx->window, mlx_scroll_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mlx_mouse_hook(mlx_t* mlx, mlx_mousefunc func, void* param)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
MLX_NONNULL(func);
|
||||||
|
|
||||||
|
mlx_ctx_t* const mlxctx = mlx->context;
|
||||||
|
mlxctx->mouse_hook.func = func;
|
||||||
|
mlxctx->mouse_hook.param = param;
|
||||||
|
glfwSetMouseButtonCallback(mlx->window, mlx_mouse_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mlx_cursor_hook(mlx_t* mlx, mlx_cursorfunc func, void* param)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
MLX_NONNULL(func);
|
||||||
|
|
||||||
|
mlx_ctx_t* const mlxctx = mlx->context;
|
||||||
|
mlxctx->cursor_hook.func = func;
|
||||||
|
mlxctx->cursor_hook.param = param;
|
||||||
|
glfwSetCursorPosCallback(mlx->window, mlx_cursor_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mlx_is_mouse_down(mlx_t* mlx, mouse_key_t key)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
|
||||||
|
return (glfwGetMouseButton(mlx->window, key) == GLFW_PRESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mlx_set_mouse_pos(mlx_t* mlx, int32_t x, int32_t y)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
|
||||||
|
glfwSetCursorPos(mlx->window, (double)x, (double)y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mlx_get_mouse_pos(mlx_t* mlx, int32_t* x, int32_t* y)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
MLX_NONNULL(x);
|
||||||
|
MLX_NONNULL(y);
|
||||||
|
|
||||||
|
double xd, yd;
|
||||||
|
glfwGetCursorPos(mlx->window, &xd, &yd);
|
||||||
|
*x = (int32_t)xd;
|
||||||
|
*y = (int32_t)yd;
|
||||||
|
}
|
34
MLX42/src/mlx_put_pixel.c
Normal file
34
MLX42/src/mlx_put_pixel.c
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* :::::::: */
|
||||||
|
/* mlx_put_pixel.c :+: :+: */
|
||||||
|
/* +:+ */
|
||||||
|
/* By: W2Wizard <w2.wizzard@gmail.com> +#+ */
|
||||||
|
/* +#+ */
|
||||||
|
/* Created: 2021/12/28 03:30:13 by W2Wizard #+# #+# */
|
||||||
|
/* Updated: 2022/06/29 16:00:30 by lde-la-h ######## odam.nl */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include "MLX42/MLX42_Int.h"
|
||||||
|
|
||||||
|
// BUG: Linux may experience a red hue instead due to endiannes
|
||||||
|
void mlx_draw_pixel(uint8_t* pixel, uint32_t color)
|
||||||
|
{
|
||||||
|
*(pixel++) = (uint8_t)(color >> 24);
|
||||||
|
*(pixel++) = (uint8_t)(color >> 16);
|
||||||
|
*(pixel++) = (uint8_t)(color >> 8);
|
||||||
|
*(pixel++) = (uint8_t)(color & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
//= Public =//
|
||||||
|
|
||||||
|
void mlx_put_pixel(mlx_image_t* image, uint32_t x, uint32_t y, uint32_t color)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(image);
|
||||||
|
MLX_ASSERT(x < image->width, "Pixel is out of bounds");
|
||||||
|
MLX_ASSERT(y < image->height, "Pixel is out of bounds");
|
||||||
|
|
||||||
|
uint8_t* pixelstart = &image->pixels[(y * image->width + x) * BPP];
|
||||||
|
mlx_draw_pixel(pixelstart, color);
|
||||||
|
}
|
137
MLX42/src/mlx_window.c
Normal file
137
MLX42/src/mlx_window.c
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* :::::::: */
|
||||||
|
/* mlx_window.c :+: :+: */
|
||||||
|
/* +:+ */
|
||||||
|
/* By: W2wizard <w2wizzard@gmail.com> +#+ */
|
||||||
|
/* +#+ */
|
||||||
|
/* Created: 2022/02/08 01:14:59 by W2wizard #+# #+# */
|
||||||
|
/* Updated: 2022/11/22 09:06:54 by jvan-hal ######## odam.nl */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include "MLX42/MLX42_Int.h"
|
||||||
|
|
||||||
|
//= Private =//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recalculate the view projection matrix, used by images for screen pos
|
||||||
|
* Reference: https://bit.ly/3KuHOu1 (Matrix View Projection)
|
||||||
|
*/
|
||||||
|
void mlx_update_matrix(const mlx_t* mlx, int32_t width, int32_t height)
|
||||||
|
{
|
||||||
|
const mlx_ctx_t* mlxctx = mlx->context;
|
||||||
|
const float depth = mlxctx->zdepth;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In case the setting to stretch the image is set, we maintain the width and height but not
|
||||||
|
* the depth.
|
||||||
|
*/
|
||||||
|
width = mlx_settings[MLX_STRETCH_IMAGE] ? mlxctx->initialWidth : mlx->width;
|
||||||
|
height = mlx_settings[MLX_STRETCH_IMAGE] ? mlxctx->initialHeight : mlx->height;
|
||||||
|
|
||||||
|
const float matrix[16] = {
|
||||||
|
2.f / width, 0, 0, 0,
|
||||||
|
0, 2.f / -(height), 0, 0,
|
||||||
|
0, 0, -2.f / (depth - -depth), 0,
|
||||||
|
-1, -(height / -height),
|
||||||
|
-((depth + -depth) / (depth - -depth)), 1
|
||||||
|
};
|
||||||
|
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(mlxctx->shaderprogram, "ProjMatrix"), 1, GL_FALSE, matrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mlx_resize_callback(GLFWwindow* window, int32_t width, int32_t height)
|
||||||
|
{
|
||||||
|
const mlx_t* mlx = glfwGetWindowUserPointer(window);
|
||||||
|
const mlx_ctx_t* mlxctx = mlx->context;
|
||||||
|
|
||||||
|
if (mlxctx->resize_hook.func)
|
||||||
|
mlxctx->resize_hook.func(width, height, mlxctx->resize_hook.param);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mlx_close_callback(GLFWwindow* window)
|
||||||
|
{
|
||||||
|
const mlx_t* mlx = glfwGetWindowUserPointer(window);
|
||||||
|
const mlx_close_t close_hook = ((mlx_ctx_t*)mlx->context)->close_hook;
|
||||||
|
|
||||||
|
close_hook.func(close_hook.param);
|
||||||
|
}
|
||||||
|
|
||||||
|
//= Public =//
|
||||||
|
|
||||||
|
void mlx_close_hook(mlx_t* mlx, mlx_closefunc func, void* param)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
MLX_NONNULL(func);
|
||||||
|
|
||||||
|
mlx_ctx_t* mlxctx = mlx->context;
|
||||||
|
mlxctx->close_hook.func = func;
|
||||||
|
mlxctx->close_hook.param = param;
|
||||||
|
glfwSetWindowCloseCallback(mlx->window, mlx_close_callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mlx_resize_hook(mlx_t* mlx, mlx_resizefunc func, void* param)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
MLX_NONNULL(func);
|
||||||
|
|
||||||
|
mlx_ctx_t* mlxctx = mlx->context;
|
||||||
|
mlxctx->resize_hook.func = func;
|
||||||
|
mlxctx->resize_hook.param = param;
|
||||||
|
glfwSetWindowSizeCallback(mlx->window, mlx_resize_callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mlx_set_icon(mlx_t* mlx, mlx_texture_t* image)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
MLX_NONNULL(image);
|
||||||
|
|
||||||
|
const GLFWimage icon = {
|
||||||
|
.width = image->width,
|
||||||
|
.height = image->height,
|
||||||
|
.pixels = image->pixels
|
||||||
|
};
|
||||||
|
|
||||||
|
glfwSetWindowIcon(mlx->window, 1, &icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mlx_set_window_pos(mlx_t* mlx, int32_t xpos, int32_t ypos)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
|
||||||
|
glfwSetWindowPos(mlx->window, xpos, ypos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mlx_get_window_pos(mlx_t* mlx, int32_t* xpos, int32_t* ypos)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
MLX_NONNULL(xpos);
|
||||||
|
MLX_NONNULL(ypos);
|
||||||
|
|
||||||
|
glfwGetWindowPos(mlx->window, xpos, ypos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mlx_set_window_size(mlx_t* mlx, int32_t new_width, int32_t new_height)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
|
||||||
|
mlx->width = new_width;
|
||||||
|
mlx->height = new_height;
|
||||||
|
glfwSetWindowSize(mlx->window, new_width, new_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mlx_set_window_limit(mlx_t* mlx, int32_t min_w, int32_t min_h, int32_t max_w, int32_t max_h)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
|
||||||
|
glfwSetWindowSizeLimits(mlx->window, min_w, min_h, max_w, max_h);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mlx_set_window_title(mlx_t* mlx, const char* title)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
MLX_NONNULL(title);
|
||||||
|
|
||||||
|
glfwSetWindowTitle(mlx->window, title);
|
||||||
|
}
|
35
MLX42/src/textures/mlx_png.c
Normal file
35
MLX42/src/textures/mlx_png.c
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* :::::::: */
|
||||||
|
/* mlx_png.c :+: :+: */
|
||||||
|
/* +:+ */
|
||||||
|
/* By: W2Wizard <w2.wizzard@gmail.com> +#+ */
|
||||||
|
/* +#+ */
|
||||||
|
/* Created: 2022/02/16 23:11:29 by W2Wizard #+# #+# */
|
||||||
|
/* Updated: 2022/06/27 19:55:06 by lde-la-h ######## odam.nl */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include "MLX42/MLX42_Int.h"
|
||||||
|
|
||||||
|
//= Public =//
|
||||||
|
|
||||||
|
mlx_texture_t* mlx_load_png(const char* path)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(path);
|
||||||
|
|
||||||
|
mlx_texture_t* image;
|
||||||
|
if (!(image = malloc(sizeof(mlx_texture_t))))
|
||||||
|
return ((void*)mlx_error(MLX_MEMFAIL));
|
||||||
|
|
||||||
|
uint32_t error;
|
||||||
|
image->bytes_per_pixel = BPP;
|
||||||
|
if ((error = lodepng_decode32_file(&image->pixels, &image->width, &image->height, path)))
|
||||||
|
{
|
||||||
|
free(image);
|
||||||
|
// Explicitly print error on purpose
|
||||||
|
fprintf(stderr, "MLX42: LodePNG: %s\n", lodepng_error_text(error));
|
||||||
|
return ((void*)mlx_error(MLX_INVPNG));
|
||||||
|
}
|
||||||
|
return (image);
|
||||||
|
}
|
42
MLX42/src/textures/mlx_texture.c
Normal file
42
MLX42/src/textures/mlx_texture.c
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* :::::::: */
|
||||||
|
/* mlx_texture.c :+: :+: */
|
||||||
|
/* +:+ */
|
||||||
|
/* By: W2Wizard <main@w2wizard.dev> +#+ */
|
||||||
|
/* +#+ */
|
||||||
|
/* Created: 2022/02/17 01:02:24 by W2Wizard #+# #+# */
|
||||||
|
/* Updated: 2023/03/09 11:03:47 by W2Wizard ######## odam.nl */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include "MLX42/MLX42_Int.h"
|
||||||
|
|
||||||
|
//= Public =//
|
||||||
|
|
||||||
|
mlx_image_t* mlx_texture_to_image(mlx_t* mlx, mlx_texture_t* texture)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
MLX_NONNULL(texture);
|
||||||
|
|
||||||
|
mlx_image_t* image = mlx_new_image(mlx, texture->width, texture->height);
|
||||||
|
if (image == NULL)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
uint8_t* pixelx;
|
||||||
|
uint8_t* pixeli;
|
||||||
|
for (uint32_t i = 0; i < texture->height; i++)
|
||||||
|
{
|
||||||
|
pixelx = &texture->pixels[(i * texture->width) * texture->bytes_per_pixel];
|
||||||
|
pixeli = &image->pixels[(i * image->width) * texture->bytes_per_pixel];
|
||||||
|
memmove(pixeli, pixelx, texture->width * texture->bytes_per_pixel);
|
||||||
|
}
|
||||||
|
return (image);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mlx_delete_texture(mlx_texture_t* texture)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(texture);
|
||||||
|
|
||||||
|
mlx_freen(2, texture->pixels, texture);
|
||||||
|
}
|
208
MLX42/src/textures/mlx_xpm42.c
Normal file
208
MLX42/src/textures/mlx_xpm42.c
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* :::::::: */
|
||||||
|
/* mlx_xpm42.c :+: :+: */
|
||||||
|
/* +:+ */
|
||||||
|
/* By: W2Wizard <w2.wizzard@gmail.com> +#+ */
|
||||||
|
/* +#+ */
|
||||||
|
/* Created: 2021/12/28 03:42:29 by W2Wizard #+# #+# */
|
||||||
|
/* Updated: 2022/06/27 19:58:33 by lde-la-h ######## odam.nl */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include "MLX42/MLX42_Int.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XPM is an obscure image format which can't seem to make up its mind
|
||||||
|
* whether it wants to be written in C code or not.
|
||||||
|
*
|
||||||
|
* https://en.wikipedia.org/wiki/X_PixMap
|
||||||
|
*
|
||||||
|
* This might anger some but instead I decided to write my own
|
||||||
|
* image format, very similar to XPM2, which seems to be the better
|
||||||
|
* option between the 3 versions. The only difference is in the
|
||||||
|
* header which carries the file type, width, height, color count
|
||||||
|
* and finally color type aka 'c' for RGBA8 or 'm' for monochrome
|
||||||
|
* output.
|
||||||
|
*
|
||||||
|
* The changes, in my opinion, very much simplify the XPM format
|
||||||
|
* into something literally anybody can use without much guessing
|
||||||
|
* as to what does what.
|
||||||
|
*
|
||||||
|
* Additionally with the C style format, the idea is that you simply include
|
||||||
|
* it directly into the compilation of the program (since it's just C).
|
||||||
|
*
|
||||||
|
* As convenient as this is, I just find it hideous especially the XPM3 variant.
|
||||||
|
* By sticking to the XPM style format, conversion should be very easy and
|
||||||
|
* straightforward to this format however.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//= Private =//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses HEX color channel e.g: "0F"
|
||||||
|
*
|
||||||
|
* @param channel The 2 character string to parse.
|
||||||
|
* @return Int value of the channel.
|
||||||
|
*/
|
||||||
|
static uint8_t mlx_parse_hex_channel(char* channel)
|
||||||
|
{
|
||||||
|
char temp_chan[] = {channel[0], channel[1], '\0'};
|
||||||
|
return (strtol(temp_chan, NULL, 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the XPM color value entry e.g: ".X #00FF00FF"
|
||||||
|
* into the color table while also verifying the format.
|
||||||
|
*
|
||||||
|
* @param xpm The XPM.
|
||||||
|
* @param line The line to parse.
|
||||||
|
* @param ctable The color hash table.
|
||||||
|
* @param s Size of the hash table
|
||||||
|
* @return True or false depending on if it sucessfully parsed the line.
|
||||||
|
*/
|
||||||
|
static bool mlx_insert_xpm_entry(xpm_t* xpm, char* line, uint32_t* ctable, size_t s)
|
||||||
|
{
|
||||||
|
// NOTE: uintptr because windows likes to complain...
|
||||||
|
// Verify the length of the Pixel string by checking backwards for the first
|
||||||
|
// occurence of a space and then check the distance by comparing with cpp.
|
||||||
|
if (((uintptr_t)strrchr(line, ' ') - (uintptr_t)line) != (uint64_t)xpm->cpp)
|
||||||
|
return (false);
|
||||||
|
if (!isspace(line[xpm->cpp]) || line[xpm->cpp + 1] != '#' || !isalnum(line[xpm->cpp + 2]))
|
||||||
|
return (false);
|
||||||
|
|
||||||
|
uint32_t color = 0;
|
||||||
|
size_t start_offset = xpm->cpp + 2;
|
||||||
|
color |= mlx_parse_hex_channel(line + start_offset) << 24;
|
||||||
|
color |= mlx_parse_hex_channel(line + start_offset + 2) << 16;
|
||||||
|
color |= mlx_parse_hex_channel(line + start_offset + 4) << 8;
|
||||||
|
color |= mlx_parse_hex_channel(line + start_offset + 6);
|
||||||
|
|
||||||
|
int32_t index = mlx_fnv_hash(line, xpm->cpp) % s;
|
||||||
|
ctable[index] = xpm->mode == 'm' ? mlx_rgba_to_mono(color) : color;
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the pixel data line by line and then processes each pixel
|
||||||
|
* by hashing the characters and looking it up from the color table.
|
||||||
|
*
|
||||||
|
* @param xpm The XPM.
|
||||||
|
* @param file The filepath to the XPM42 file.
|
||||||
|
* @param ctable The color hash table.
|
||||||
|
* @param s Size of the hash table.
|
||||||
|
* @return True or false depending on if it sucessfully parsed the line.
|
||||||
|
*/
|
||||||
|
static bool mlx_read_data(xpm_t* xpm, FILE* file, uint32_t* ctable, size_t s)
|
||||||
|
{
|
||||||
|
size_t line_len;
|
||||||
|
char* line = NULL;
|
||||||
|
|
||||||
|
for (int64_t y_xpm = 0; y_xpm < xpm->texture.height; y_xpm++)
|
||||||
|
{
|
||||||
|
if (!mlx_getline(&line, &line_len, file))
|
||||||
|
return (free(line), false);
|
||||||
|
if (line[line_len - 1] == '\n')
|
||||||
|
line_len--;
|
||||||
|
if (line_len != xpm->texture.width * xpm->cpp)
|
||||||
|
return (free(line), false);
|
||||||
|
|
||||||
|
// NOTE: Copy pixel by pixel as we need to retrieve the hash table.
|
||||||
|
for (int64_t x_xpm = 0, x_line = 0; x_xpm < xpm->texture.width; x_xpm++, x_line += xpm->cpp)
|
||||||
|
{
|
||||||
|
uint8_t* pixelstart = &xpm->texture.pixels[(y_xpm * xpm->texture.width + x_xpm) * BPP];
|
||||||
|
mlx_draw_pixel(pixelstart, ctable[mlx_fnv_hash(&line[x_line], xpm->cpp) % s]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(line);
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For quick lookups we basically create a stack allocated lookup
|
||||||
|
* table with every ascii character in it. This should help avoid a O(n)
|
||||||
|
* case and give us a O(1) for very fast look ups.
|
||||||
|
*
|
||||||
|
* Downside is we still need to iterate over each pixel to solve its color.
|
||||||
|
* So I hope this makes it at least a bit faster.
|
||||||
|
*
|
||||||
|
* TODO: This buffer might be way to big! Do actual collision checks,
|
||||||
|
* for now just straight up raw dog this.
|
||||||
|
*/
|
||||||
|
static bool mlx_read_table(xpm_t* xpm, FILE* file)
|
||||||
|
{
|
||||||
|
char* line = NULL;
|
||||||
|
size_t line_len;
|
||||||
|
uint32_t ctable[UINT16_MAX] = {0};
|
||||||
|
|
||||||
|
for (int32_t i = 0; i < xpm->color_count; i++)
|
||||||
|
{
|
||||||
|
if (!mlx_getline(&line, &line_len, file))
|
||||||
|
return (free(line), false);
|
||||||
|
if (!mlx_insert_xpm_entry(xpm, line, ctable, (sizeof(ctable) / BPP)))
|
||||||
|
return (free(line), false);
|
||||||
|
}
|
||||||
|
free(line);
|
||||||
|
return (mlx_read_data(xpm, file, ctable, (sizeof(ctable) / BPP)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the XPM42 file header which usually consists of a
|
||||||
|
* file type declaration of "!XPM42" followed by the next line
|
||||||
|
* containing image information such as width, height, unique color
|
||||||
|
* count and finally the color mode. Which is either c for Color or
|
||||||
|
* m for Monochrome.
|
||||||
|
*/
|
||||||
|
static bool mlx_read_xpm_header(xpm_t* xpm, FILE *file)
|
||||||
|
{
|
||||||
|
int32_t flagc;
|
||||||
|
char buffer[64] = {0};
|
||||||
|
|
||||||
|
// Check file type dec...
|
||||||
|
if (!fgets(buffer, sizeof(buffer), file))
|
||||||
|
return (false);
|
||||||
|
if (strncmp(buffer, "!XPM42\n", sizeof(buffer)) != 0)
|
||||||
|
return (false);
|
||||||
|
|
||||||
|
// Get header info ...
|
||||||
|
if (!fgets(buffer, sizeof(buffer), file))
|
||||||
|
return (false);
|
||||||
|
flagc = sscanf(buffer, "%i %i %i %i %c\n", &xpm->texture.width, &xpm->texture.height, &xpm->color_count, &xpm->cpp, &xpm->mode);
|
||||||
|
if (flagc < 4 || xpm->texture.width > INT16_MAX || xpm->texture.height > INT16_MAX || \
|
||||||
|
!(xpm->mode == 'c' || xpm->mode == 'm') || xpm->cpp > 10)
|
||||||
|
return (false);
|
||||||
|
xpm->texture.bytes_per_pixel = BPP;
|
||||||
|
xpm->texture.pixels = calloc(xpm->texture.width * xpm->texture.height, sizeof(int32_t));
|
||||||
|
return (xpm->texture.pixels != NULL ? mlx_read_table(xpm, file) : false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//= Public =//
|
||||||
|
|
||||||
|
xpm_t* mlx_load_xpm42(const char* path)
|
||||||
|
{
|
||||||
|
FILE* file;
|
||||||
|
xpm_t* xpm = NULL;
|
||||||
|
|
||||||
|
MLX_NONNULL(path);
|
||||||
|
if (!strstr(path, ".xpm42"))
|
||||||
|
return ((void*)mlx_error(MLX_INVEXT));
|
||||||
|
if (!(file = fopen(path, "r")))
|
||||||
|
return ((void*)mlx_error(MLX_INVFILE));
|
||||||
|
if (!(xpm = calloc(1, sizeof(xpm_t))))
|
||||||
|
return ((void*)mlx_error(MLX_MEMFAIL));
|
||||||
|
if (!mlx_read_xpm_header(xpm, file))
|
||||||
|
{
|
||||||
|
mlx_freen(2, xpm->texture.pixels, xpm);
|
||||||
|
mlx_error(MLX_INVXPM);
|
||||||
|
xpm = NULL;
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
return (xpm);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mlx_delete_xpm42(xpm_t* xpm)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(xpm);
|
||||||
|
free(xpm->texture.pixels);
|
||||||
|
free(xpm);
|
||||||
|
}
|
31
MLX42/src/utils/mlx_compare.c
Normal file
31
MLX42/src/utils/mlx_compare.c
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* :::::::: */
|
||||||
|
/* mlx_comparison.c :+: :+: */
|
||||||
|
/* +:+ */
|
||||||
|
/* By: jvan-hal <jvan-hal@student.codam.nl> +#+ */
|
||||||
|
/* +#+ */
|
||||||
|
/* Created: 2023/01/31 17:20:19 by jvan-hal #+# #+# */
|
||||||
|
/* Updated: 2023/01/31 17:23:49 by jvan-hal ######## odam.nl */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include "MLX42/MLX42_Int.h"
|
||||||
|
|
||||||
|
//= Private =//
|
||||||
|
|
||||||
|
bool mlx_equal_image(void* lstcontent, void* value)
|
||||||
|
{
|
||||||
|
const mlx_image_t* lcontent = lstcontent;
|
||||||
|
const mlx_image_t* lvalue = value;
|
||||||
|
|
||||||
|
return (lcontent == lvalue);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mlx_equal_inst(void* lstcontent, void* value)
|
||||||
|
{
|
||||||
|
const draw_queue_t* lcontent = lstcontent;
|
||||||
|
const mlx_image_t* lvalue = value;
|
||||||
|
|
||||||
|
return (lcontent->image == lvalue);
|
||||||
|
}
|
60
MLX42/src/utils/mlx_error.c
Normal file
60
MLX42/src/utils/mlx_error.c
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* :::::::: */
|
||||||
|
/* mlx_error.c :+: :+: */
|
||||||
|
/* +:+ */
|
||||||
|
/* By: W2Wizard <w2.wizzard@gmail.com> +#+ */
|
||||||
|
/* +#+ */
|
||||||
|
/* Created: 2021/12/28 02:51:54 by W2Wizard #+# #+# */
|
||||||
|
/* Updated: 2022/11/22 08:50:15 by jvan-hal ######## odam.nl */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include "MLX42/MLX42_Int.h"
|
||||||
|
|
||||||
|
//= Private =//
|
||||||
|
|
||||||
|
// English description of the error codes.
|
||||||
|
static const char* mlx_errors[MLX_ERRMAX] = {
|
||||||
|
"No Errors",
|
||||||
|
"File has invalid extension",
|
||||||
|
"Failed to open the file",
|
||||||
|
"PNG file is invalid or corrupted",
|
||||||
|
"XPM42 file is invalid or corrupted",
|
||||||
|
"The specified X or Y positions are out of bounds",
|
||||||
|
"The specified Width or Height dimensions are out of bounds",
|
||||||
|
"The provided image is invalid, might indicate mismanagement of images",
|
||||||
|
"Failed to compile the vertex shader.",
|
||||||
|
"Failed to compile the fragment shader.",
|
||||||
|
"Failed to compile the shaders.",
|
||||||
|
"Failed to allocate memory",
|
||||||
|
"Failed to initialize GLAD",
|
||||||
|
"Failed to initialize GLFW",
|
||||||
|
"Failed to create window",
|
||||||
|
"String is too big to be drawn",
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functions to set the error number, simply for convenience.
|
||||||
|
*
|
||||||
|
* @param val The error value.
|
||||||
|
* @return Always false
|
||||||
|
*/
|
||||||
|
bool mlx_error(mlx_errno_t val)
|
||||||
|
{
|
||||||
|
mlx_errno = val;
|
||||||
|
#ifndef NDEBUG
|
||||||
|
fprintf(stderr, "MLX42: %s", mlx_strerror(mlx_errno));
|
||||||
|
#endif
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//= Public =//
|
||||||
|
|
||||||
|
const char* mlx_strerror(mlx_errno_t val)
|
||||||
|
{
|
||||||
|
MLX_ASSERT(val >= 0, "Index must be positive");
|
||||||
|
MLX_ASSERT(val < MLX_ERRMAX, "Index out of bounds");
|
||||||
|
|
||||||
|
return (mlx_errors[val]);
|
||||||
|
}
|
176
MLX42/src/utils/mlx_list.c
Normal file
176
MLX42/src/utils/mlx_list.c
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* :::::::: */
|
||||||
|
/* mlx_list.c :+: :+: */
|
||||||
|
/* +:+ */
|
||||||
|
/* By: W2Wizard <main@w2wizard.dev> +#+ */
|
||||||
|
/* +#+ */
|
||||||
|
/* Created: 2021/12/28 01:53:51 by W2Wizard #+# #+# */
|
||||||
|
/* Updated: 2023/02/27 11:31:01 by W2Wizard ######## odam.nl */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include "MLX42/MLX42_Int.h"
|
||||||
|
|
||||||
|
//= Private =//
|
||||||
|
|
||||||
|
int32_t mlx_lstsize(mlx_list_t* lst)
|
||||||
|
{
|
||||||
|
int32_t i;
|
||||||
|
|
||||||
|
for (i = 0; lst != NULL; i++)
|
||||||
|
lst = lst->next;
|
||||||
|
return (i);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mlx_lstdelone(mlx_list_t* lst, void (*del)(void *))
|
||||||
|
{
|
||||||
|
if (del != NULL)
|
||||||
|
del(lst->content);
|
||||||
|
free(lst);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mlx_lstclear(mlx_list_t** lst, void (*del)(void*))
|
||||||
|
{
|
||||||
|
mlx_list_t* next_lst;
|
||||||
|
|
||||||
|
while (*lst != NULL)
|
||||||
|
{
|
||||||
|
next_lst = (*lst)->next;
|
||||||
|
mlx_lstdelone(*lst, del);
|
||||||
|
*lst = next_lst;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mlx_list_t* mlx_lstnew(void* content)
|
||||||
|
{
|
||||||
|
mlx_list_t* out = NULL;
|
||||||
|
|
||||||
|
if ((out = malloc(sizeof(mlx_list_t))))
|
||||||
|
{
|
||||||
|
out->content = content;
|
||||||
|
out->next = NULL;
|
||||||
|
out->prev = NULL;
|
||||||
|
}
|
||||||
|
return (out);
|
||||||
|
}
|
||||||
|
|
||||||
|
mlx_list_t* mlx_lstlast(mlx_list_t* lst)
|
||||||
|
{
|
||||||
|
if (!lst)
|
||||||
|
return (NULL);
|
||||||
|
while (lst->next)
|
||||||
|
lst = lst->next;
|
||||||
|
return (lst);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mlx_lstadd_back(mlx_list_t** lst, mlx_list_t* new)
|
||||||
|
{
|
||||||
|
if (!lst || !new)
|
||||||
|
return;
|
||||||
|
if (!*lst)
|
||||||
|
*lst = new;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mlx_list_t* temp = mlx_lstlast(*lst);
|
||||||
|
new->prev = temp;
|
||||||
|
temp->next = new;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mlx_lstadd_front(mlx_list_t** lst, mlx_list_t* new)
|
||||||
|
{
|
||||||
|
if (!lst || !new)
|
||||||
|
return;
|
||||||
|
if ((*lst) != NULL)
|
||||||
|
(*lst)->prev = new;
|
||||||
|
new->next = *lst;
|
||||||
|
new->prev = NULL;
|
||||||
|
*lst = new;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the specified content from the list, if found.
|
||||||
|
* Also fixes any relinking that might be needed.
|
||||||
|
*
|
||||||
|
* @param[in] lst The list
|
||||||
|
* @param[in] comp Function to check if the content and value are the same.
|
||||||
|
* @returns The removed element, clean up as you wish.
|
||||||
|
*/
|
||||||
|
mlx_list_t* mlx_lstremove(mlx_list_t** lst, void* value, bool (*comp)(void*, void*))
|
||||||
|
{
|
||||||
|
mlx_list_t* lstcpy = *lst;
|
||||||
|
|
||||||
|
while (lstcpy && !comp(lstcpy->content, value))
|
||||||
|
lstcpy = lstcpy->next;
|
||||||
|
if (lstcpy == NULL)
|
||||||
|
return (NULL);
|
||||||
|
if (lstcpy == *lst)
|
||||||
|
*lst = lstcpy->next;
|
||||||
|
if (lstcpy->next != NULL)
|
||||||
|
lstcpy->next->prev = lstcpy->prev;
|
||||||
|
if (lstcpy->prev != NULL)
|
||||||
|
lstcpy->prev->next = lstcpy->next;
|
||||||
|
return (lstcpy);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve Z value from queue.
|
||||||
|
static int32_t mlx_getzdata(mlx_list_t* entry)
|
||||||
|
{
|
||||||
|
const draw_queue_t* queue = entry->content;
|
||||||
|
|
||||||
|
return (queue->image->instances[queue->instanceid].z);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert the entry back into head sorted.
|
||||||
|
static void mlx_insertsort(mlx_list_t** head, mlx_list_t* new)
|
||||||
|
{
|
||||||
|
mlx_list_t* current;
|
||||||
|
|
||||||
|
if (*head == NULL)
|
||||||
|
*head = new;
|
||||||
|
else if (mlx_getzdata(*head) >= mlx_getzdata(new))
|
||||||
|
{
|
||||||
|
new->next = *head;
|
||||||
|
new->next->prev = new;
|
||||||
|
*head = new;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current = *head;
|
||||||
|
|
||||||
|
// Find insertion location.
|
||||||
|
while (current->next != NULL && mlx_getzdata(current->next) < mlx_getzdata(new))
|
||||||
|
current = current->next;
|
||||||
|
new->next = current->next;
|
||||||
|
|
||||||
|
// Insert at the end
|
||||||
|
if (current->next != NULL)
|
||||||
|
new->next->prev = new;
|
||||||
|
current->next = new;
|
||||||
|
new->prev = current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Okay-ish sorting algorithm to sort the render queue / doubly linked list.
|
||||||
|
* We need to do this to fix transparency.
|
||||||
|
*
|
||||||
|
* @param lst The render queue.
|
||||||
|
*/
|
||||||
|
void mlx_sort_renderqueue(mlx_list_t** lst)
|
||||||
|
{
|
||||||
|
mlx_list_t* sorted = NULL;
|
||||||
|
mlx_list_t* lstcpy = *lst;
|
||||||
|
|
||||||
|
while (lstcpy != NULL)
|
||||||
|
{
|
||||||
|
mlx_list_t* next = lstcpy->next;
|
||||||
|
|
||||||
|
// Separate entry out of list and insert it back but sorted.
|
||||||
|
lstcpy->prev = lstcpy->next = NULL;
|
||||||
|
mlx_insertsort(&sorted, lstcpy);
|
||||||
|
lstcpy = next;
|
||||||
|
}
|
||||||
|
*lst = sorted;
|
||||||
|
}
|
131
MLX42/src/utils/mlx_utils.c
Normal file
131
MLX42/src/utils/mlx_utils.c
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* :::::::: */
|
||||||
|
/* mlx_utils.c :+: :+: */
|
||||||
|
/* +:+ */
|
||||||
|
/* By: W2Wizard <w2.wizzard@gmail.com> +#+ */
|
||||||
|
/* +#+ */
|
||||||
|
/* Created: 2022/01/03 20:13:17 by W2Wizard #+# #+# */
|
||||||
|
/* Updated: 2022/11/22 10:56:09 by jvan-hal ######## odam.nl */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include "MLX42/MLX42_Int.h"
|
||||||
|
|
||||||
|
//= Private =//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to read a file stream line by line, reusing the same output pointer.
|
||||||
|
* Since the same output pointer is reused it should only be freed once, either on success or failure.
|
||||||
|
* This function is made to be somewhat similar to getline.
|
||||||
|
* Getline can't be used directly since it's not standard and therefore not available on all platforms.
|
||||||
|
*
|
||||||
|
* @param out Pointer to store output string.
|
||||||
|
* @param out_size Pointer to store output strings length.
|
||||||
|
* @param file File stream to read from.
|
||||||
|
* @return True if line was read, false if EOF was reached or an error occurred.
|
||||||
|
*/
|
||||||
|
bool mlx_getline(char** out, size_t* out_size, FILE* file)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(out);
|
||||||
|
MLX_NONNULL(out_size);
|
||||||
|
MLX_NONNULL(file);
|
||||||
|
|
||||||
|
size_t size = 0;
|
||||||
|
char* temp = NULL;
|
||||||
|
static char BUFF[GETLINE_BUFF + 1]; // Add space for '\0'
|
||||||
|
|
||||||
|
if (*out) *out[0] = '\0';
|
||||||
|
|
||||||
|
while (fgets(BUFF, sizeof(BUFF), file))
|
||||||
|
{
|
||||||
|
size += strlen(BUFF);
|
||||||
|
if (!(temp = realloc(*out, sizeof(char) * size + 1)))
|
||||||
|
return (false);
|
||||||
|
if (*out == NULL)
|
||||||
|
memset(temp, '\0', size);
|
||||||
|
temp[size] = '\0';
|
||||||
|
|
||||||
|
*out = temp;
|
||||||
|
*out_size = size;
|
||||||
|
|
||||||
|
strncat(*out, BUFF, size);
|
||||||
|
if (strrchr(BUFF, '\n'))
|
||||||
|
return (true);
|
||||||
|
memset(BUFF, '\0', sizeof(BUFF));
|
||||||
|
}
|
||||||
|
return (size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String hashing algorithm using FNV-1a.
|
||||||
|
* Source: https://bit.ly/3JcRGHa
|
||||||
|
*
|
||||||
|
* @param str The string to hash
|
||||||
|
* @param len The length of the string.
|
||||||
|
* @return The hashed output.
|
||||||
|
*/
|
||||||
|
uint64_t mlx_fnv_hash(char* str, size_t len)
|
||||||
|
{
|
||||||
|
const uint64_t fnv_prime = 0x100000001b3;
|
||||||
|
const uint64_t fnv_offset = 0xcbf29ce484222325;
|
||||||
|
uint64_t hash = fnv_offset;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
hash ^= str[i];
|
||||||
|
hash *= fnv_prime;
|
||||||
|
}
|
||||||
|
return (hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility function that lets you free x amount of pointers.
|
||||||
|
*
|
||||||
|
* @param count The amount of args provided.
|
||||||
|
* @param ... Any form of pointer.
|
||||||
|
* @return False, this is simply for convenience when necessary.
|
||||||
|
*/
|
||||||
|
bool mlx_freen(int32_t count, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, count);
|
||||||
|
for (int32_t i = 0; i < count; i++)
|
||||||
|
free(va_arg(args, void*));
|
||||||
|
va_end(args);
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an RGBA value to a monochrome/grayscale value.
|
||||||
|
* It does so using specific weights for each channel.
|
||||||
|
*
|
||||||
|
* @see https://goodcalculators.com/rgb-to-grayscale-conversion-calculator/
|
||||||
|
*
|
||||||
|
* @param color The input RGBA value.
|
||||||
|
* @return The rgba value converted to a grayscale color.
|
||||||
|
*/
|
||||||
|
uint32_t mlx_rgba_to_mono(uint32_t color)
|
||||||
|
{
|
||||||
|
const uint8_t r = 0.299f * ((color >> 24) & 0xFF);
|
||||||
|
const uint8_t g = 0.587f * ((color >> 16) & 0xFF);
|
||||||
|
const uint8_t b = 0.114f * ((color >> 8) & 0xFF);
|
||||||
|
const uint8_t y = r + g + b;
|
||||||
|
|
||||||
|
return (y << 24 | y << 16 | y << 8 | (color & 0xFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
//= Public =//
|
||||||
|
|
||||||
|
double mlx_get_time(void)
|
||||||
|
{
|
||||||
|
return (glfwGetTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
void mlx_focus(mlx_t* mlx)
|
||||||
|
{
|
||||||
|
MLX_NONNULL(mlx);
|
||||||
|
|
||||||
|
glfwFocusWindow(mlx->window);
|
||||||
|
}
|
40
MLX42/tests/CMakeLists.txt
Normal file
40
MLX42/tests/CMakeLists.txt
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Codam Coding College, Amsterdam @ 2022-2023 by Jelle van Kraaij.
|
||||||
|
# See README in the root project for more information.
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
set(TEST_EXECUTABLE_NAME unit_tests)
|
||||||
|
|
||||||
|
# Download GoogleTest
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
include(GoogleTest)
|
||||||
|
include(FetchContent)
|
||||||
|
|
||||||
|
FetchContent_Declare(
|
||||||
|
googletest
|
||||||
|
DOWNLOAD_EXTRACT_TIMESTAMP
|
||||||
|
GIT_REPOSITORY https://github.com/google/googletest
|
||||||
|
GIT_TAG v1.13.0
|
||||||
|
)
|
||||||
|
|
||||||
|
FetchContent_MakeAvailable(googletest)
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
add_executable(
|
||||||
|
${TEST_EXECUTABLE_NAME}
|
||||||
|
tests.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(
|
||||||
|
${TEST_EXECUTABLE_NAME}
|
||||||
|
GTest::gtest_main
|
||||||
|
mlx42
|
||||||
|
)
|
||||||
|
|
||||||
|
set_property(TARGET ${TEST_EXECUTABLE_NAME} PROPERTY CXX_STANDARD 14)
|
||||||
|
|
||||||
|
# Add tests to CTest
|
||||||
|
# Set working directory to the the testing folder so that the test can find their test files
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
gtest_discover_tests(${TEST_EXECUTABLE_NAME} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} TEST_PREFIX "MLX42.")
|
||||||
|
enable_testing()
|
37
MLX42/tests/WindowFixture.hpp
Normal file
37
MLX42/tests/WindowFixture.hpp
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Codam Coding College, Amsterdam @ 2022-2023 by Jelle van Kraaij.
|
||||||
|
// See README in the root project for more information.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# pragma once
|
||||||
|
|
||||||
|
# include <gtest/gtest.h>
|
||||||
|
# include <MLX42/MLX42.h>
|
||||||
|
|
||||||
|
class Window : public ::testing::Test
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
mlx_t* mlx = nullptr;
|
||||||
|
|
||||||
|
static constexpr const char* name = "MLX42";
|
||||||
|
static const int32_t height = 400;
|
||||||
|
static const int32_t width = 400;
|
||||||
|
|
||||||
|
inline void SetUp() override
|
||||||
|
{
|
||||||
|
// reset error code as it is shared between tests
|
||||||
|
mlx_errno = MLX_SUCCESS;
|
||||||
|
mlx_set_setting(MLX_HEADLESS, true);
|
||||||
|
ASSERT_EQ(mlx_errno, MLX_SUCCESS);
|
||||||
|
mlx = mlx_init(width, height, name, false);
|
||||||
|
ASSERT_NE(mlx, nullptr);
|
||||||
|
ASSERT_EQ(mlx_errno, MLX_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void TearDown() override
|
||||||
|
{
|
||||||
|
ASSERT_NE(mlx, nullptr);
|
||||||
|
mlx_terminate(mlx);
|
||||||
|
ASSERT_EQ(mlx_errno, MLX_SUCCESS);
|
||||||
|
}
|
||||||
|
};
|
139
MLX42/tests/tests.cpp
Normal file
139
MLX42/tests/tests.cpp
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Codam Coding College, Amsterdam @ 2022-2023 by Jelle van Kraaij.
|
||||||
|
// See README in the root project for more information.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// If your new to gtest follow the following documentation:
|
||||||
|
// http://google.github.io/googletest/primer.html
|
||||||
|
|
||||||
|
#include "WindowFixture.hpp"
|
||||||
|
|
||||||
|
// --------------------------------------------
|
||||||
|
// Fixture for window tests
|
||||||
|
// For every TEST_F(window, ...) the SetUp() and TearDown() functions are called
|
||||||
|
// MLX can be accessed via the mlx variable in each test
|
||||||
|
// For the implementation of the fixture see tests/windowFixture.hpp
|
||||||
|
// --------------------------------------------
|
||||||
|
|
||||||
|
TEST_F(Window, Basic)
|
||||||
|
{
|
||||||
|
// Basic window is already tested in the fixture
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// NOTE: This test cannot be runned with a fixture because the settings need to be set before the window is created
|
||||||
|
TEST(MWindow, Settings)
|
||||||
|
{
|
||||||
|
mlx_errno = MLX_SUCCESS;
|
||||||
|
mlx_set_setting(MLX_STRETCH_IMAGE, true);
|
||||||
|
mlx_set_setting(MLX_MAXIMIZED, true);
|
||||||
|
mlx_set_setting(MLX_DECORATED, true);
|
||||||
|
mlx_set_setting(MLX_FULLSCREEN, true);
|
||||||
|
|
||||||
|
mlx_set_setting(MLX_HEADLESS, true);
|
||||||
|
ASSERT_EQ(mlx_errno, MLX_SUCCESS);
|
||||||
|
mlx_t *mlx = mlx_init(400, 400, "MLX42", false);
|
||||||
|
ASSERT_NE(mlx, nullptr);
|
||||||
|
ASSERT_EQ(mlx_errno, MLX_SUCCESS);
|
||||||
|
|
||||||
|
mlx_terminate(mlx);
|
||||||
|
ASSERT_EQ(mlx_errno, MLX_SUCCESS);
|
||||||
|
|
||||||
|
// Set all settings to default
|
||||||
|
mlx_set_setting(MLX_STRETCH_IMAGE, false);
|
||||||
|
mlx_set_setting(MLX_FULLSCREEN, false);
|
||||||
|
mlx_set_setting(MLX_MAXIMIZED, false);
|
||||||
|
mlx_set_setting(MLX_DECORATED, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(Window, SingleImage)
|
||||||
|
{
|
||||||
|
mlx_image_t* img = mlx_new_image(mlx, Window::width / 2, Window::height / 2);
|
||||||
|
ASSERT_NE(img, nullptr);
|
||||||
|
ASSERT_EQ(mlx_errno, MLX_SUCCESS);
|
||||||
|
|
||||||
|
int32_t val = mlx_image_to_window(mlx, img, Window::width / 4 , Window::height / 4);
|
||||||
|
EXPECT_GE(val, 0);
|
||||||
|
ASSERT_EQ(mlx_errno, MLX_SUCCESS);
|
||||||
|
|
||||||
|
mlx_delete_image(mlx, img);
|
||||||
|
ASSERT_EQ(mlx_errno, MLX_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(Window, MultipleImages)
|
||||||
|
{
|
||||||
|
mlx_image_t* img1 = mlx_new_image(mlx, Window::width / 2, Window::height / 2);
|
||||||
|
ASSERT_NE(img1, nullptr);
|
||||||
|
ASSERT_EQ(mlx_errno, MLX_SUCCESS);
|
||||||
|
|
||||||
|
mlx_image_t* img2 = mlx_new_image(mlx, Window::width, Window::height);
|
||||||
|
ASSERT_NE(img2, nullptr);
|
||||||
|
ASSERT_EQ(mlx_errno, MLX_SUCCESS);
|
||||||
|
|
||||||
|
int32_t val1 = mlx_image_to_window(mlx, img1, Window::width / 4, Window::height / 4);
|
||||||
|
EXPECT_GE(val1, 0);
|
||||||
|
ASSERT_EQ(mlx_errno, MLX_SUCCESS);
|
||||||
|
|
||||||
|
int32_t val2 = mlx_image_to_window(mlx, img2, 0, 0);
|
||||||
|
EXPECT_GE(val2, 0);
|
||||||
|
ASSERT_EQ(mlx_errno, MLX_SUCCESS);
|
||||||
|
|
||||||
|
mlx_delete_image(mlx, img1);
|
||||||
|
ASSERT_EQ(mlx_errno, MLX_SUCCESS);
|
||||||
|
|
||||||
|
mlx_delete_image(mlx, img2);
|
||||||
|
ASSERT_EQ(mlx_errno, MLX_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ft_draw(void* param)
|
||||||
|
{
|
||||||
|
static char buf[256];
|
||||||
|
static int32_t count = 0;
|
||||||
|
static mlx_image_t* img = nullptr;
|
||||||
|
mlx_t* mlx = (mlx_t*)param;
|
||||||
|
|
||||||
|
if (img == nullptr)
|
||||||
|
{
|
||||||
|
mlx_delete_image(mlx, img);
|
||||||
|
ASSERT_EQ(mlx_errno, MLX_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cheap itoa lol
|
||||||
|
memset(buf, '\0', sizeof(buf));
|
||||||
|
snprintf(buf, sizeof(buf), "%d", count);
|
||||||
|
|
||||||
|
img = mlx_put_string(mlx, buf, 0, 0);
|
||||||
|
ASSERT_NE(img, nullptr);
|
||||||
|
ASSERT_EQ(mlx_errno, MLX_SUCCESS);
|
||||||
|
|
||||||
|
if (count >= 420)
|
||||||
|
{
|
||||||
|
mlx_close_window(mlx);
|
||||||
|
ASSERT_EQ(mlx_errno, MLX_SUCCESS);
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(Window, stringTortureTest)
|
||||||
|
{
|
||||||
|
mlx_image_t *img = mlx_new_image(mlx, Window::width / 2, Window::height / 2);
|
||||||
|
ASSERT_NE(img, nullptr);
|
||||||
|
ASSERT_EQ(mlx_errno, MLX_SUCCESS);
|
||||||
|
|
||||||
|
memset(img->pixels, 255, sizeof(int32_t) * img->width * img->height);
|
||||||
|
|
||||||
|
int32_t val_window = mlx_image_to_window(mlx, img, Window::width / 4 , Window::height / 4);
|
||||||
|
EXPECT_GE(val_window, 0);
|
||||||
|
ASSERT_EQ(mlx_errno, MLX_SUCCESS);
|
||||||
|
|
||||||
|
bool val_hook = mlx_loop_hook(mlx, ft_draw, mlx);
|
||||||
|
EXPECT_EQ(val_hook, true);
|
||||||
|
ASSERT_EQ(mlx_errno, MLX_SUCCESS);
|
||||||
|
|
||||||
|
mlx_loop(mlx);
|
||||||
|
ASSERT_EQ(mlx_errno, MLX_SUCCESS);
|
||||||
|
|
||||||
|
mlx_delete_image(mlx, img);
|
||||||
|
ASSERT_EQ(mlx_errno, MLX_SUCCESS);
|
||||||
|
}
|
47
MLX42/tools/compile_shader.bat
Executable file
47
MLX42/tools/compile_shader.bat
Executable file
@ -0,0 +1,47 @@
|
|||||||
|
:: -----------------------------------------------------------------------------
|
||||||
|
:: Codam Coding College, Amsterdam @ 2022-2023 by W2Wizard.
|
||||||
|
:: See README in the root project for more information.
|
||||||
|
:: -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@echo off
|
||||||
|
SETLOCAL DisableDelayedExpansion
|
||||||
|
|
||||||
|
:: go to usage function if no arguments have been given to the script
|
||||||
|
IF [%1]==[] GOTO usage
|
||||||
|
|
||||||
|
:: check if input file exists before continuing
|
||||||
|
IF NOT EXIST %1 GOTO fnotfound
|
||||||
|
|
||||||
|
SET SHADERTYPE=%~x1
|
||||||
|
SET SHADERTYPE=%SHADERTYPE:~1%
|
||||||
|
|
||||||
|
echo // -----------------------------------------------------------------------------
|
||||||
|
echo // Codam Coding College, Amsterdam @ <2022-2023> by W2Wizard.
|
||||||
|
echo // See README in the root project for more information.
|
||||||
|
echo // -----------------------------------------------------------------------------
|
||||||
|
echo.
|
||||||
|
echo // If you wish to modify this file edit the .vert or .frag file!
|
||||||
|
echo.
|
||||||
|
echo #include "MLX42/MLX42_Int.h"
|
||||||
|
echo.
|
||||||
|
|
||||||
|
FOR /F "delims=" %%A IN (%1) DO IF NOT DEFINED VERSIONLINE set "VERSIONLINE=%%A"
|
||||||
|
echo const char* %SHADERTYPE%_shader = "%VERSIONLINE%\n"
|
||||||
|
FOR /F "skip=1 delims=" %%A IN (%1) DO (
|
||||||
|
IF "%%A" == "}" (echo "%%A";) ELSE (echo "%%A")
|
||||||
|
)
|
||||||
|
|
||||||
|
ENDLOCAL
|
||||||
|
EXIT /B 0
|
||||||
|
|
||||||
|
:: usage function exits the script with exit code 3 (path not found)
|
||||||
|
:usage
|
||||||
|
echo ERROR: missing arguments, use as follows: %0 ^<ShaderFile^> 1>&2
|
||||||
|
ENDLOCAL
|
||||||
|
EXIT /B 3
|
||||||
|
|
||||||
|
:: fnotfound function exits the script with exit code 2 (file not found)
|
||||||
|
:fnotfound
|
||||||
|
echo ERROR: shader file not found: %1 1>&2
|
||||||
|
ENDLOCAL
|
||||||
|
EXIT /B 2
|
44
MLX42/tools/compile_shader.sh
Executable file
44
MLX42/tools/compile_shader.sh
Executable file
@ -0,0 +1,44 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Codam Coding College, Amsterdam @ 2022-2023 by W2Wizard.
|
||||||
|
# See README in the root project for more information.
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# If no arguments have been given, exit with error code 1
|
||||||
|
if [ "$#" -ne 1 ]; then
|
||||||
|
echo "ERROR: missing arguments, use as follows: $0 <ShaderFile>" 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If file cannot be found, exit with error code 2
|
||||||
|
if [ ! -f "$1" ]; then
|
||||||
|
echo "ERROR: shader file not found: $1" 1>&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
SHADERTYPE="${1##*.}"
|
||||||
|
|
||||||
|
echo "// -----------------------------------------------------------------------------"
|
||||||
|
echo "// Codam Coding College, Amsterdam @ 2022-2023 by W2Wizard. "
|
||||||
|
echo "// See README in the root project for more information. "
|
||||||
|
echo "// -----------------------------------------------------------------------------"
|
||||||
|
echo ""
|
||||||
|
echo "// If you wish to modify this file edit the .vert or .frag file!"
|
||||||
|
echo ""
|
||||||
|
echo "#include \"MLX42/MLX42_Int.h\""
|
||||||
|
echo ""
|
||||||
|
echo "const char* ${SHADERTYPE}_shader = \"$(sed -n '1{p;q;}' "$1")\\n\""
|
||||||
|
{
|
||||||
|
# Skip over first line
|
||||||
|
read
|
||||||
|
while IFS= read -r LINE; do
|
||||||
|
if [ ! "${LINE}" = "" ]; then
|
||||||
|
if [ "${LINE}" = "}" ]; then
|
||||||
|
echo " \"${LINE}\";"
|
||||||
|
else
|
||||||
|
echo " \"${LINE}\""
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
} < "$1"
|
||||||
|
exit 0
|
815
MLX42/tools/xpm3_conv.py
Executable file
815
MLX42/tools/xpm3_conv.py
Executable file
@ -0,0 +1,815 @@
|
|||||||
|
# **************************************************************************** #
|
||||||
|
# #
|
||||||
|
# :::::::: #
|
||||||
|
# xpm3_conv.py :+: :+: #
|
||||||
|
# +:+ #
|
||||||
|
# By: pvan-dij <pvan-dij@student.codam.nl> +#+ #
|
||||||
|
# +#+ #
|
||||||
|
# Created: 2022/02/09 21:04:31 by pvan-dij #+# #+# #
|
||||||
|
# Updated: 2022/02/23 16:48:19 by lde-la-h ######## odam.nl #
|
||||||
|
# #
|
||||||
|
# **************************************************************************** #
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# This script takes an XPM3 as argument and converts it to XPM42.
|
||||||
|
|
||||||
|
# This is a generated dictionary from the XFree86 distribution.
|
||||||
|
colours = {
|
||||||
|
"snow":"fffafa",
|
||||||
|
"ghost white":"f8f8ff",
|
||||||
|
"ghostwhite":"f8f8ff",
|
||||||
|
"white smoke":"f5f5f5",
|
||||||
|
"whitesmoke":"f5f5f5",
|
||||||
|
"gainsboro":"dcdcdc",
|
||||||
|
"floral white":"fffaf0",
|
||||||
|
"floralwhite":"fffaf0",
|
||||||
|
"old lace":"fdf5e6",
|
||||||
|
"oldlace":"fdf5e6",
|
||||||
|
"linen":"faf0e6",
|
||||||
|
"antique white":"faebd7",
|
||||||
|
"antiquewhite":"faebd7",
|
||||||
|
"papaya whip":"ffefd5",
|
||||||
|
"papayawhip":"ffefd5",
|
||||||
|
"blanched almond":"ffebcd",
|
||||||
|
"blanchedalmond":"ffebcd",
|
||||||
|
"bisque":"ffe4c4",
|
||||||
|
"peach puff":"ffdab9",
|
||||||
|
"peachpuff":"ffdab9",
|
||||||
|
"navajo white":"ffdead",
|
||||||
|
"navajowhite":"ffdead",
|
||||||
|
"moccasin":"ffe4b5",
|
||||||
|
"cornsilk":"fff8dc",
|
||||||
|
"ivory":"fffff0",
|
||||||
|
"lemon chiffon":"fffacd",
|
||||||
|
"lemonchiffon":"fffacd",
|
||||||
|
"seashell":"fff5ee",
|
||||||
|
"honeydew":"f0fff0",
|
||||||
|
"mint cream":"f5fffa",
|
||||||
|
"mintcream":"f5fffa",
|
||||||
|
"azure":"f0ffff",
|
||||||
|
"alice blue":"f0f8ff",
|
||||||
|
"aliceblue":"f0f8ff",
|
||||||
|
"lavender":"e6e6fa",
|
||||||
|
"lavender blush":"fff0f5",
|
||||||
|
"lavenderblush":"fff0f5",
|
||||||
|
"misty rose":"ffe4e1",
|
||||||
|
"mistyrose":"ffe4e1",
|
||||||
|
"white":"ffffff",
|
||||||
|
"black":"000000",
|
||||||
|
"dark slate":"2f4f4f",
|
||||||
|
"darkslategray":"2f4f4f",
|
||||||
|
"dark slate":"2f4f4f",
|
||||||
|
"darkslategrey":"2f4f4f",
|
||||||
|
"dim gray":"696969",
|
||||||
|
"dimgray":"696969",
|
||||||
|
"dim grey":"696969",
|
||||||
|
"dimgrey":"696969",
|
||||||
|
"slate gray":"708090",
|
||||||
|
"slategray":"708090",
|
||||||
|
"slate grey":"708090",
|
||||||
|
"slategrey":"708090",
|
||||||
|
"light slate":"778899",
|
||||||
|
"lightslategray":"778899",
|
||||||
|
"light slate":"778899",
|
||||||
|
"lightslategrey":"778899",
|
||||||
|
"gray":"bebebe",
|
||||||
|
"grey":"bebebe",
|
||||||
|
"light grey":"d3d3d3",
|
||||||
|
"lightgrey":"d3d3d3",
|
||||||
|
"light gray":"d3d3d3",
|
||||||
|
"lightgray":"d3d3d3",
|
||||||
|
"midnight blue":"191970",
|
||||||
|
"midnightblue":"191970",
|
||||||
|
"navy":"000080",
|
||||||
|
"navy blue":"000080",
|
||||||
|
"navyblue":"000080",
|
||||||
|
"cornflower blue":"6495ed",
|
||||||
|
"cornflowerblue":"6495ed",
|
||||||
|
"dark slate":"483d8b",
|
||||||
|
"darkslateblue":"483d8b",
|
||||||
|
"slate blue":"6a5acd",
|
||||||
|
"slateblue":"6a5acd",
|
||||||
|
"medium slate":"7b68ee",
|
||||||
|
"mediumslateblue":"7b68ee",
|
||||||
|
"light slate":"8470ff",
|
||||||
|
"lightslateblue":"8470ff",
|
||||||
|
"medium blue":"0000cd",
|
||||||
|
"mediumblue":"0000cd",
|
||||||
|
"royal blue":"4169e1",
|
||||||
|
"royalblue":"4169e1",
|
||||||
|
"blue":"0000ff",
|
||||||
|
"dodger blue":"1e90ff",
|
||||||
|
"dodgerblue":"1e90ff",
|
||||||
|
"deep sky":"bfff",
|
||||||
|
"deepskyblue":"bfff",
|
||||||
|
"sky blue":"87ceeb",
|
||||||
|
"skyblue":"87ceeb",
|
||||||
|
"light sky":"87cefa",
|
||||||
|
"lightskyblue":"87cefa",
|
||||||
|
"steel blue":"4682b4",
|
||||||
|
"steelblue":"4682b4",
|
||||||
|
"light steel":"b0c4de",
|
||||||
|
"lightsteelblue":"b0c4de",
|
||||||
|
"light blue":"add8e6",
|
||||||
|
"lightblue":"add8e6",
|
||||||
|
"powder blue":"b0e0e6",
|
||||||
|
"powderblue":"b0e0e6",
|
||||||
|
"pale turquoise":"afeeee",
|
||||||
|
"paleturquoise":"afeeee",
|
||||||
|
"dark turquoise":"ced1",
|
||||||
|
"darkturquoise":"ced1",
|
||||||
|
"medium turquoise":"48d1cc",
|
||||||
|
"mediumturquoise":"48d1cc",
|
||||||
|
"turquoise":"40e0d0",
|
||||||
|
"cyan":"00ffff",
|
||||||
|
"light cyan":"e0ffff",
|
||||||
|
"lightcyan":"e0ffff",
|
||||||
|
"cadet blue":"5f9ea0",
|
||||||
|
"cadetblue":"5f9ea0",
|
||||||
|
"medium aquamarine":"66cdaa",
|
||||||
|
"mediumaquamarine":"66cdaa",
|
||||||
|
"aquamarine":"7fffd4",
|
||||||
|
"dark green":"006400",
|
||||||
|
"darkgreen":"006400",
|
||||||
|
"dark olive":"556b2f",
|
||||||
|
"darkolivegreen":"556b2f",
|
||||||
|
"dark sea":"8fbc8f",
|
||||||
|
"darkseagreen":"8fbc8f",
|
||||||
|
"sea green":"2e8b57",
|
||||||
|
"seagreen":"2e8b57",
|
||||||
|
"medium sea":"3cb371",
|
||||||
|
"mediumseagreen":"3cb371",
|
||||||
|
"light sea":"20b2aa",
|
||||||
|
"lightseagreen":"20b2aa",
|
||||||
|
"pale green":"98fb98",
|
||||||
|
"palegreen":"98fb98",
|
||||||
|
"spring green":"00ff7f",
|
||||||
|
"springgreen":"00ff7f",
|
||||||
|
"lawn green":"7cfc00",
|
||||||
|
"lawngreen":"7cfc00",
|
||||||
|
"green":"00ff00",
|
||||||
|
"chartreuse":"7fff00",
|
||||||
|
"medium spring":"00fa9a",
|
||||||
|
"mediumspringgreen":"00fa9a",
|
||||||
|
"green yellow":"adff2f",
|
||||||
|
"greenyellow":"adff2f",
|
||||||
|
"lime green":"32cd32",
|
||||||
|
"limegreen":"32cd32",
|
||||||
|
"yellow green":"9acd32",
|
||||||
|
"yellowgreen":"9acd32",
|
||||||
|
"forest green":"228b22",
|
||||||
|
"forestgreen":"228b22",
|
||||||
|
"olive drab":"6b8e23",
|
||||||
|
"olivedrab":"6b8e23",
|
||||||
|
"dark khaki":"bdb76b",
|
||||||
|
"darkkhaki":"bdb76b",
|
||||||
|
"khaki":"f0e68c",
|
||||||
|
"pale goldenrod":"eee8aa",
|
||||||
|
"palegoldenrod":"eee8aa",
|
||||||
|
"light goldenrod":"fafad2",
|
||||||
|
"lightgoldenrodyellow":"fafad2",
|
||||||
|
"light yellow":"ffffe0",
|
||||||
|
"lightyellow":"ffffe0",
|
||||||
|
"yellow":"ffff00",
|
||||||
|
"gold":"ffd700",
|
||||||
|
"light goldenrod":"eedd82",
|
||||||
|
"lightgoldenrod":"eedd82",
|
||||||
|
"goldenrod":"daa520",
|
||||||
|
"dark goldenrod":"b8860b",
|
||||||
|
"darkgoldenrod":"b8860b",
|
||||||
|
"rosy brown":"bc8f8f",
|
||||||
|
"rosybrown":"bc8f8f",
|
||||||
|
"indian red":"cd5c5c",
|
||||||
|
"indianred":"cd5c5c",
|
||||||
|
"saddle brown":"8b4513",
|
||||||
|
"saddlebrown":"8b4513",
|
||||||
|
"sienna":"a0522d",
|
||||||
|
"peru":"cd853f",
|
||||||
|
"burlywood":"deb887",
|
||||||
|
"beige":"f5f5dc",
|
||||||
|
"wheat":"f5deb3",
|
||||||
|
"sandy brown":"f4a460",
|
||||||
|
"sandybrown":"f4a460",
|
||||||
|
"tan":"d2b48c",
|
||||||
|
"chocolate":"d2691e",
|
||||||
|
"firebrick":"b22222",
|
||||||
|
"brown":"a52a2a",
|
||||||
|
"dark salmon":"e9967a",
|
||||||
|
"darksalmon":"e9967a",
|
||||||
|
"salmon":"fa8072",
|
||||||
|
"light salmon":"ffa07a",
|
||||||
|
"lightsalmon":"ffa07a",
|
||||||
|
"orange":"ffa500",
|
||||||
|
"dark orange":"ff8c00",
|
||||||
|
"darkorange":"ff8c00",
|
||||||
|
"coral":"ff7f50",
|
||||||
|
"light coral":"f08080",
|
||||||
|
"lightcoral":"f08080",
|
||||||
|
"tomato":"ff6347",
|
||||||
|
"orange red":"ff4500",
|
||||||
|
"orangered":"ff4500",
|
||||||
|
"red":"ff0000",
|
||||||
|
"hot pink":"ff69b4",
|
||||||
|
"hotpink":"ff69b4",
|
||||||
|
"deep pink":"ff1493",
|
||||||
|
"deeppink":"ff1493",
|
||||||
|
"pink":"ffc0cb",
|
||||||
|
"light pink":"ffb6c1",
|
||||||
|
"lightpink":"ffb6c1",
|
||||||
|
"pale violet":"db7093",
|
||||||
|
"palevioletred":"db7093",
|
||||||
|
"maroon":"b03060",
|
||||||
|
"medium violet":"c71585",
|
||||||
|
"mediumvioletred":"c71585",
|
||||||
|
"violet red":"d02090",
|
||||||
|
"violetred":"d02090",
|
||||||
|
"magenta":"ff00ff",
|
||||||
|
"violet":"ee82ee",
|
||||||
|
"plum":"dda0dd",
|
||||||
|
"orchid":"da70d6",
|
||||||
|
"medium orchid":"ba55d3",
|
||||||
|
"mediumorchid":"ba55d3",
|
||||||
|
"dark orchid":"9932cc",
|
||||||
|
"darkorchid":"9932cc",
|
||||||
|
"dark violet":"9400d3",
|
||||||
|
"darkviolet":"9400d3",
|
||||||
|
"blue violet":"8a2be2",
|
||||||
|
"blueviolet":"8a2be2",
|
||||||
|
"purple":"a020f0",
|
||||||
|
"medium purple":"9370db",
|
||||||
|
"mediumpurple":"9370db",
|
||||||
|
"thistle":"d8bfd8",
|
||||||
|
"snow1":"fffafa",
|
||||||
|
"snow2":"eee9e9",
|
||||||
|
"snow3":"cdc9c9",
|
||||||
|
"snow4":"8b8989",
|
||||||
|
"seashell1":"fff5ee",
|
||||||
|
"seashell2":"eee5de",
|
||||||
|
"seashell3":"cdc5bf",
|
||||||
|
"seashell4":"8b8682",
|
||||||
|
"antiquewhite1":"ffefdb",
|
||||||
|
"antiquewhite2":"eedfcc",
|
||||||
|
"antiquewhite3":"cdc0b0",
|
||||||
|
"antiquewhite4":"8b8378",
|
||||||
|
"bisque1":"ffe4c4",
|
||||||
|
"bisque2":"eed5b7",
|
||||||
|
"bisque3":"cdb79e",
|
||||||
|
"bisque4":"8b7d6b",
|
||||||
|
"peachpuff1":"ffdab9",
|
||||||
|
"peachpuff2":"eecbad",
|
||||||
|
"peachpuff3":"cdaf95",
|
||||||
|
"peachpuff4":"8b7765",
|
||||||
|
"navajowhite1":"ffdead",
|
||||||
|
"navajowhite2":"eecfa1",
|
||||||
|
"navajowhite3":"cdb38b",
|
||||||
|
"navajowhite4":"8b795e",
|
||||||
|
"lemonchiffon1":"fffacd",
|
||||||
|
"lemonchiffon2":"eee9bf",
|
||||||
|
"lemonchiffon3":"cdc9a5",
|
||||||
|
"lemonchiffon4":"8b8970",
|
||||||
|
"cornsilk1":"fff8dc",
|
||||||
|
"cornsilk2":"eee8cd",
|
||||||
|
"cornsilk3":"cdc8b1",
|
||||||
|
"cornsilk4":"8b8878",
|
||||||
|
"ivory1":"fffff0",
|
||||||
|
"ivory2":"eeeee0",
|
||||||
|
"ivory3":"cdcdc1",
|
||||||
|
"ivory4":"8b8b83",
|
||||||
|
"honeydew1":"f0fff0",
|
||||||
|
"honeydew2":"e0eee0",
|
||||||
|
"honeydew3":"c1cdc1",
|
||||||
|
"honeydew4":"838b83",
|
||||||
|
"lavenderblush1":"fff0f5",
|
||||||
|
"lavenderblush2":"eee0e5",
|
||||||
|
"lavenderblush3":"cdc1c5",
|
||||||
|
"lavenderblush4":"8b8386",
|
||||||
|
"mistyrose1":"ffe4e1",
|
||||||
|
"mistyrose2":"eed5d2",
|
||||||
|
"mistyrose3":"cdb7b5",
|
||||||
|
"mistyrose4":"8b7d7b",
|
||||||
|
"azure1":"f0ffff",
|
||||||
|
"azure2":"e0eeee",
|
||||||
|
"azure3":"c1cdcd",
|
||||||
|
"azure4":"838b8b",
|
||||||
|
"slateblue1":"836fff",
|
||||||
|
"slateblue2":"7a67ee",
|
||||||
|
"slateblue3":"6959cd",
|
||||||
|
"slateblue4":"473c8b",
|
||||||
|
"royalblue1":"4876ff",
|
||||||
|
"royalblue2":"436eee",
|
||||||
|
"royalblue3":"3a5fcd",
|
||||||
|
"royalblue4":"27408b",
|
||||||
|
"blue1":"0000ff",
|
||||||
|
"blue2":"0000ee",
|
||||||
|
"blue3":"0000cd",
|
||||||
|
"blue4":"00008b",
|
||||||
|
"dodgerblue1":"1e90ff",
|
||||||
|
"dodgerblue2":"1c86ee",
|
||||||
|
"dodgerblue3":"1874cd",
|
||||||
|
"dodgerblue4":"104e8b",
|
||||||
|
"steelblue1":"63b8ff",
|
||||||
|
"steelblue2":"5cacee",
|
||||||
|
"steelblue3":"4f94cd",
|
||||||
|
"steelblue4":"36648b",
|
||||||
|
"deepskyblue1":"bfff",
|
||||||
|
"deepskyblue2":"b2ee",
|
||||||
|
"deepskyblue3":"9acd",
|
||||||
|
"deepskyblue4":"688b",
|
||||||
|
"skyblue1":"87ceff",
|
||||||
|
"skyblue2":"7ec0ee",
|
||||||
|
"skyblue3":"6ca6cd",
|
||||||
|
"skyblue4":"4a708b",
|
||||||
|
"lightskyblue1":"b0e2ff",
|
||||||
|
"lightskyblue2":"a4d3ee",
|
||||||
|
"lightskyblue3":"8db6cd",
|
||||||
|
"lightskyblue4":"607b8b",
|
||||||
|
"slategray1":"c6e2ff",
|
||||||
|
"slategray2":"b9d3ee",
|
||||||
|
"slategray3":"9fb6cd",
|
||||||
|
"slategray4":"6c7b8b",
|
||||||
|
"lightsteelblue1":"cae1ff",
|
||||||
|
"lightsteelblue2":"bcd2ee",
|
||||||
|
"lightsteelblue3":"a2b5cd",
|
||||||
|
"lightsteelblue4":"6e7b8b",
|
||||||
|
"lightblue1":"bfefff",
|
||||||
|
"lightblue2":"b2dfee",
|
||||||
|
"lightblue3":"9ac0cd",
|
||||||
|
"lightblue4":"68838b",
|
||||||
|
"lightcyan1":"e0ffff",
|
||||||
|
"lightcyan2":"d1eeee",
|
||||||
|
"lightcyan3":"b4cdcd",
|
||||||
|
"lightcyan4":"7a8b8b",
|
||||||
|
"paleturquoise1":"bbffff",
|
||||||
|
"paleturquoise2":"aeeeee",
|
||||||
|
"paleturquoise3":"96cdcd",
|
||||||
|
"paleturquoise4":"668b8b",
|
||||||
|
"cadetblue1":"98f5ff",
|
||||||
|
"cadetblue2":"8ee5ee",
|
||||||
|
"cadetblue3":"7ac5cd",
|
||||||
|
"cadetblue4":"53868b",
|
||||||
|
"turquoise1":"f5ff",
|
||||||
|
"turquoise2":"e5ee",
|
||||||
|
"turquoise3":"c5cd",
|
||||||
|
"turquoise4":"868b",
|
||||||
|
"cyan1":"ffff",
|
||||||
|
"cyan2":"eeee",
|
||||||
|
"cyan3":"cdcd",
|
||||||
|
"cyan4":"8b8b",
|
||||||
|
"darkslategray1":"97ffff",
|
||||||
|
"darkslategray2":"8deeee",
|
||||||
|
"darkslategray3":"79cdcd",
|
||||||
|
"darkslategray4":"528b8b",
|
||||||
|
"aquamarine1":"7fffd4",
|
||||||
|
"aquamarine2":"76eec6",
|
||||||
|
"aquamarine3":"66cdaa",
|
||||||
|
"aquamarine4":"458b74",
|
||||||
|
"darkseagreen1":"c1ffc1",
|
||||||
|
"darkseagreen2":"b4eeb4",
|
||||||
|
"darkseagreen3":"9bcd9b",
|
||||||
|
"darkseagreen4":"698b69",
|
||||||
|
"seagreen1":"54ff9f",
|
||||||
|
"seagreen2":"4eee94",
|
||||||
|
"seagreen3":"43cd80",
|
||||||
|
"seagreen4":"2e8b57",
|
||||||
|
"palegreen1":"9aff9a",
|
||||||
|
"palegreen2":"90ee90",
|
||||||
|
"palegreen3":"7ccd7c",
|
||||||
|
"palegreen4":"548b54",
|
||||||
|
"springgreen1":"ff7f",
|
||||||
|
"springgreen2":"ee76",
|
||||||
|
"springgreen3":"cd66",
|
||||||
|
"springgreen4":"8b45",
|
||||||
|
"green1":"ff00",
|
||||||
|
"green2":"ee00",
|
||||||
|
"green3":"cd00",
|
||||||
|
"green4":"8b00",
|
||||||
|
"chartreuse1":"7fff00",
|
||||||
|
"chartreuse2":"76ee00",
|
||||||
|
"chartreuse3":"66cd00",
|
||||||
|
"chartreuse4":"458b00",
|
||||||
|
"olivedrab1":"c0ff3e",
|
||||||
|
"olivedrab2":"b3ee3a",
|
||||||
|
"olivedrab3":"9acd32",
|
||||||
|
"olivedrab4":"698b22",
|
||||||
|
"darkolivegreen1":"caff70",
|
||||||
|
"darkolivegreen2":"bcee68",
|
||||||
|
"darkolivegreen3":"a2cd5a",
|
||||||
|
"darkolivegreen4":"6e8b3d",
|
||||||
|
"khaki1":"fff68f",
|
||||||
|
"khaki2":"eee685",
|
||||||
|
"khaki3":"cdc673",
|
||||||
|
"khaki4":"8b864e",
|
||||||
|
"lightgoldenrod1":"ffec8b",
|
||||||
|
"lightgoldenrod2":"eedc82",
|
||||||
|
"lightgoldenrod3":"cdbe70",
|
||||||
|
"lightgoldenrod4":"8b814c",
|
||||||
|
"lightyellow1":"ffffe0",
|
||||||
|
"lightyellow2":"eeeed1",
|
||||||
|
"lightyellow3":"cdcdb4",
|
||||||
|
"lightyellow4":"8b8b7a",
|
||||||
|
"yellow1":"ffff00",
|
||||||
|
"yellow2":"eeee00",
|
||||||
|
"yellow3":"cdcd00",
|
||||||
|
"yellow4":"8b8b00",
|
||||||
|
"gold1":"ffd700",
|
||||||
|
"gold2":"eec900",
|
||||||
|
"gold3":"cdad00",
|
||||||
|
"gold4":"8b7500",
|
||||||
|
"goldenrod1":"ffc125",
|
||||||
|
"goldenrod2":"eeb422",
|
||||||
|
"goldenrod3":"cd9b1d",
|
||||||
|
"goldenrod4":"8b6914",
|
||||||
|
"darkgoldenrod1":"ffb90f",
|
||||||
|
"darkgoldenrod2":"eead0e",
|
||||||
|
"darkgoldenrod3":"cd950c",
|
||||||
|
"darkgoldenrod4":"8b6508",
|
||||||
|
"rosybrown1":"ffc1c1",
|
||||||
|
"rosybrown2":"eeb4b4",
|
||||||
|
"rosybrown3":"cd9b9b",
|
||||||
|
"rosybrown4":"8b6969",
|
||||||
|
"indianred1":"ff6a6a",
|
||||||
|
"indianred2":"ee6363",
|
||||||
|
"indianred3":"cd5555",
|
||||||
|
"indianred4":"8b3a3a",
|
||||||
|
"sienna1":"ff8247",
|
||||||
|
"sienna2":"ee7942",
|
||||||
|
"sienna3":"cd6839",
|
||||||
|
"sienna4":"8b4726",
|
||||||
|
"burlywood1":"ffd39b",
|
||||||
|
"burlywood2":"eec591",
|
||||||
|
"burlywood3":"cdaa7d",
|
||||||
|
"burlywood4":"8b7355",
|
||||||
|
"wheat1":"ffe7ba",
|
||||||
|
"wheat2":"eed8ae",
|
||||||
|
"wheat3":"cdba96",
|
||||||
|
"wheat4":"8b7e66",
|
||||||
|
"tan1":"ffa54f",
|
||||||
|
"tan2":"ee9a49",
|
||||||
|
"tan3":"cd853f",
|
||||||
|
"tan4":"8b5a2b",
|
||||||
|
"chocolate1":"ff7f24",
|
||||||
|
"chocolate2":"ee7621",
|
||||||
|
"chocolate3":"cd661d",
|
||||||
|
"chocolate4":"8b4513",
|
||||||
|
"firebrick1":"ff3030",
|
||||||
|
"firebrick2":"ee2c2c",
|
||||||
|
"firebrick3":"cd2626",
|
||||||
|
"firebrick4":"8b1a1a",
|
||||||
|
"brown1":"ff4040",
|
||||||
|
"brown2":"ee3b3b",
|
||||||
|
"brown3":"cd3333",
|
||||||
|
"brown4":"8b2323",
|
||||||
|
"salmon1":"ff8c69",
|
||||||
|
"salmon2":"ee8262",
|
||||||
|
"salmon3":"cd7054",
|
||||||
|
"salmon4":"8b4c39",
|
||||||
|
"lightsalmon1":"ffa07a",
|
||||||
|
"lightsalmon2":"ee9572",
|
||||||
|
"lightsalmon3":"cd8162",
|
||||||
|
"lightsalmon4":"8b5742",
|
||||||
|
"orange1":"ffa500",
|
||||||
|
"orange2":"ee9a00",
|
||||||
|
"orange3":"cd8500",
|
||||||
|
"orange4":"8b5a00",
|
||||||
|
"darkorange1":"ff7f00",
|
||||||
|
"darkorange2":"ee7600",
|
||||||
|
"darkorange3":"cd6600",
|
||||||
|
"darkorange4":"8b4500",
|
||||||
|
"coral1":"ff7256",
|
||||||
|
"coral2":"ee6a50",
|
||||||
|
"coral3":"cd5b45",
|
||||||
|
"coral4":"8b3e2f",
|
||||||
|
"tomato1":"ff6347",
|
||||||
|
"tomato2":"ee5c42",
|
||||||
|
"tomato3":"cd4f39",
|
||||||
|
"tomato4":"8b3626",
|
||||||
|
"orangered1":"ff4500",
|
||||||
|
"orangered2":"ee4000",
|
||||||
|
"orangered3":"cd3700",
|
||||||
|
"orangered4":"8b2500",
|
||||||
|
"red1":"ff0000",
|
||||||
|
"red2":"ee0000",
|
||||||
|
"red3":"cd0000",
|
||||||
|
"red4":"8b0000",
|
||||||
|
"deeppink1":"ff1493",
|
||||||
|
"deeppink2":"ee1289",
|
||||||
|
"deeppink3":"cd1076",
|
||||||
|
"deeppink4":"8b0a50",
|
||||||
|
"hotpink1":"ff6eb4",
|
||||||
|
"hotpink2":"ee6aa7",
|
||||||
|
"hotpink3":"cd6090",
|
||||||
|
"hotpink4":"8b3a62",
|
||||||
|
"pink1":"ffb5c5",
|
||||||
|
"pink2":"eea9b8",
|
||||||
|
"pink3":"cd919e",
|
||||||
|
"pink4":"8b636c",
|
||||||
|
"lightpink1":"ffaeb9",
|
||||||
|
"lightpink2":"eea2ad",
|
||||||
|
"lightpink3":"cd8c95",
|
||||||
|
"lightpink4":"8b5f65",
|
||||||
|
"palevioletred1":"ff82ab",
|
||||||
|
"palevioletred2":"ee799f",
|
||||||
|
"palevioletred3":"cd6889",
|
||||||
|
"palevioletred4":"8b475d",
|
||||||
|
"maroon1":"ff34b3",
|
||||||
|
"maroon2":"ee30a7",
|
||||||
|
"maroon3":"cd2990",
|
||||||
|
"maroon4":"8b1c62",
|
||||||
|
"violetred1":"ff3e96",
|
||||||
|
"violetred2":"ee3a8c",
|
||||||
|
"violetred3":"cd3278",
|
||||||
|
"violetred4":"8b2252",
|
||||||
|
"magenta1":"ff00ff",
|
||||||
|
"magenta2":"ee00ee",
|
||||||
|
"magenta3":"cd00cd",
|
||||||
|
"magenta4":"8b008b",
|
||||||
|
"orchid1":"ff83fa",
|
||||||
|
"orchid2":"ee7ae9",
|
||||||
|
"orchid3":"cd69c9",
|
||||||
|
"orchid4":"8b4789",
|
||||||
|
"plum1":"ffbbff",
|
||||||
|
"plum2":"eeaeee",
|
||||||
|
"plum3":"cd96cd",
|
||||||
|
"plum4":"8b668b",
|
||||||
|
"mediumorchid1":"e066ff",
|
||||||
|
"mediumorchid2":"d15fee",
|
||||||
|
"mediumorchid3":"b452cd",
|
||||||
|
"mediumorchid4":"7a378b",
|
||||||
|
"darkorchid1":"bf3eff",
|
||||||
|
"darkorchid2":"b23aee",
|
||||||
|
"darkorchid3":"9a32cd",
|
||||||
|
"darkorchid4":"68228b",
|
||||||
|
"purple1":"9b30ff",
|
||||||
|
"purple2":"912cee",
|
||||||
|
"purple3":"7d26cd",
|
||||||
|
"purple4":"551a8b",
|
||||||
|
"mediumpurple1":"ab82ff",
|
||||||
|
"mediumpurple2":"9f79ee",
|
||||||
|
"mediumpurple3":"8968cd",
|
||||||
|
"mediumpurple4":"5d478b",
|
||||||
|
"thistle1":"ffe1ff",
|
||||||
|
"thistle2":"eed2ee",
|
||||||
|
"thistle3":"cdb5cd",
|
||||||
|
"thistle4":"8b7b8b",
|
||||||
|
"gray0":"000000",
|
||||||
|
"grey0":"000000",
|
||||||
|
"gray1":"30303",
|
||||||
|
"grey1":"30303",
|
||||||
|
"gray2":"50505",
|
||||||
|
"grey2":"50505",
|
||||||
|
"gray3":"80808",
|
||||||
|
"grey3":"80808",
|
||||||
|
"gray4":"a0a0a",
|
||||||
|
"grey4":"a0a0a",
|
||||||
|
"gray5":"d0d0d",
|
||||||
|
"grey5":"d0d0d",
|
||||||
|
"gray6":"f0f0f",
|
||||||
|
"grey6":"f0f0f",
|
||||||
|
"gray7":"121212",
|
||||||
|
"grey7":"121212",
|
||||||
|
"gray8":"141414",
|
||||||
|
"grey8":"141414",
|
||||||
|
"gray9":"171717",
|
||||||
|
"grey9":"171717",
|
||||||
|
"gray10":"1a1a1a",
|
||||||
|
"grey10":"1a1a1a",
|
||||||
|
"gray11":"1c1c1c",
|
||||||
|
"grey11":"1c1c1c",
|
||||||
|
"gray12":"1f1f1f",
|
||||||
|
"grey12":"1f1f1f",
|
||||||
|
"gray13":"212121",
|
||||||
|
"grey13":"212121",
|
||||||
|
"gray14":"242424",
|
||||||
|
"grey14":"242424",
|
||||||
|
"gray15":"262626",
|
||||||
|
"grey15":"262626",
|
||||||
|
"gray16":"292929",
|
||||||
|
"grey16":"292929",
|
||||||
|
"gray17":"2b2b2b",
|
||||||
|
"grey17":"2b2b2b",
|
||||||
|
"gray18":"2e2e2e",
|
||||||
|
"grey18":"2e2e2e",
|
||||||
|
"gray19":"303030",
|
||||||
|
"grey19":"303030",
|
||||||
|
"gray20":"333333",
|
||||||
|
"grey20":"333333",
|
||||||
|
"gray21":"363636",
|
||||||
|
"grey21":"363636",
|
||||||
|
"gray22":"383838",
|
||||||
|
"grey22":"383838",
|
||||||
|
"gray23":"3b3b3b",
|
||||||
|
"grey23":"3b3b3b",
|
||||||
|
"gray24":"3d3d3d",
|
||||||
|
"grey24":"3d3d3d",
|
||||||
|
"gray25":"404040",
|
||||||
|
"grey25":"404040",
|
||||||
|
"gray26":"424242",
|
||||||
|
"grey26":"424242",
|
||||||
|
"gray27":"454545",
|
||||||
|
"grey27":"454545",
|
||||||
|
"gray28":"474747",
|
||||||
|
"grey28":"474747",
|
||||||
|
"gray29":"4a4a4a",
|
||||||
|
"grey29":"4a4a4a",
|
||||||
|
"gray30":"4d4d4d",
|
||||||
|
"grey30":"4d4d4d",
|
||||||
|
"gray31":"4f4f4f",
|
||||||
|
"grey31":"4f4f4f",
|
||||||
|
"gray32":"525252",
|
||||||
|
"grey32":"525252",
|
||||||
|
"gray33":"545454",
|
||||||
|
"grey33":"545454",
|
||||||
|
"gray34":"575757",
|
||||||
|
"grey34":"575757",
|
||||||
|
"gray35":"595959",
|
||||||
|
"grey35":"595959",
|
||||||
|
"gray36":"5c5c5c",
|
||||||
|
"grey36":"5c5c5c",
|
||||||
|
"gray37":"5e5e5e",
|
||||||
|
"grey37":"5e5e5e",
|
||||||
|
"gray38":"616161",
|
||||||
|
"grey38":"616161",
|
||||||
|
"gray39":"636363",
|
||||||
|
"grey39":"636363",
|
||||||
|
"gray40":"666666",
|
||||||
|
"grey40":"666666",
|
||||||
|
"gray41":"696969",
|
||||||
|
"grey41":"696969",
|
||||||
|
"gray42":"6b6b6b",
|
||||||
|
"grey42":"6b6b6b",
|
||||||
|
"gray43":"6e6e6e",
|
||||||
|
"grey43":"6e6e6e",
|
||||||
|
"gray44":"707070",
|
||||||
|
"grey44":"707070",
|
||||||
|
"gray45":"737373",
|
||||||
|
"grey45":"737373",
|
||||||
|
"gray46":"757575",
|
||||||
|
"grey46":"757575",
|
||||||
|
"gray47":"787878",
|
||||||
|
"grey47":"787878",
|
||||||
|
"gray48":"7a7a7a",
|
||||||
|
"grey48":"7a7a7a",
|
||||||
|
"gray49":"7d7d7d",
|
||||||
|
"grey49":"7d7d7d",
|
||||||
|
"gray50":"7f7f7f",
|
||||||
|
"grey50":"7f7f7f",
|
||||||
|
"gray51":"828282",
|
||||||
|
"grey51":"828282",
|
||||||
|
"gray52":"858585",
|
||||||
|
"grey52":"858585",
|
||||||
|
"gray53":"878787",
|
||||||
|
"grey53":"878787",
|
||||||
|
"gray54":"8a8a8a",
|
||||||
|
"grey54":"8a8a8a",
|
||||||
|
"gray55":"8c8c8c",
|
||||||
|
"grey55":"8c8c8c",
|
||||||
|
"gray56":"8f8f8f",
|
||||||
|
"grey56":"8f8f8f",
|
||||||
|
"gray57":"919191",
|
||||||
|
"grey57":"919191",
|
||||||
|
"gray58":"949494",
|
||||||
|
"grey58":"949494",
|
||||||
|
"gray59":"969696",
|
||||||
|
"grey59":"969696",
|
||||||
|
"gray60":"999999",
|
||||||
|
"grey60":"999999",
|
||||||
|
"gray61":"9c9c9c",
|
||||||
|
"grey61":"9c9c9c",
|
||||||
|
"gray62":"9e9e9e",
|
||||||
|
"grey62":"9e9e9e",
|
||||||
|
"gray63":"a1a1a1",
|
||||||
|
"grey63":"a1a1a1",
|
||||||
|
"gray64":"a3a3a3",
|
||||||
|
"grey64":"a3a3a3",
|
||||||
|
"gray65":"a6a6a6",
|
||||||
|
"grey65":"a6a6a6",
|
||||||
|
"gray66":"a8a8a8",
|
||||||
|
"grey66":"a8a8a8",
|
||||||
|
"gray67":"ababab",
|
||||||
|
"grey67":"ababab",
|
||||||
|
"gray68":"adadad",
|
||||||
|
"grey68":"adadad",
|
||||||
|
"gray69":"b0b0b0",
|
||||||
|
"grey69":"b0b0b0",
|
||||||
|
"gray70":"b3b3b3",
|
||||||
|
"grey70":"b3b3b3",
|
||||||
|
"gray71":"b5b5b5",
|
||||||
|
"grey71":"b5b5b5",
|
||||||
|
"gray72":"b8b8b8",
|
||||||
|
"grey72":"b8b8b8",
|
||||||
|
"gray73":"bababa",
|
||||||
|
"grey73":"bababa",
|
||||||
|
"gray74":"bdbdbd",
|
||||||
|
"grey74":"bdbdbd",
|
||||||
|
"gray75":"bfbfbf",
|
||||||
|
"grey75":"bfbfbf",
|
||||||
|
"gray76":"c2c2c2",
|
||||||
|
"grey76":"c2c2c2",
|
||||||
|
"gray77":"c4c4c4",
|
||||||
|
"grey77":"c4c4c4",
|
||||||
|
"gray78":"c7c7c7",
|
||||||
|
"grey78":"c7c7c7",
|
||||||
|
"gray79":"c9c9c9",
|
||||||
|
"grey79":"c9c9c9",
|
||||||
|
"gray80":"cccccc",
|
||||||
|
"grey80":"cccccc",
|
||||||
|
"gray81":"cfcfcf",
|
||||||
|
"grey81":"cfcfcf",
|
||||||
|
"gray82":"d1d1d1",
|
||||||
|
"grey82":"d1d1d1",
|
||||||
|
"gray83":"d4d4d4",
|
||||||
|
"grey83":"d4d4d4",
|
||||||
|
"gray84":"d6d6d6",
|
||||||
|
"grey84":"d6d6d6",
|
||||||
|
"gray85":"d9d9d9",
|
||||||
|
"grey85":"d9d9d9",
|
||||||
|
"gray86":"dbdbdb",
|
||||||
|
"grey86":"dbdbdb",
|
||||||
|
"gray87":"dedede",
|
||||||
|
"grey87":"dedede",
|
||||||
|
"gray88":"e0e0e0",
|
||||||
|
"grey88":"e0e0e0",
|
||||||
|
"gray89":"e3e3e3",
|
||||||
|
"grey89":"e3e3e3",
|
||||||
|
"gray90":"e5e5e5",
|
||||||
|
"grey90":"e5e5e5",
|
||||||
|
"gray91":"e8e8e8",
|
||||||
|
"grey91":"e8e8e8",
|
||||||
|
"gray92":"ebebeb",
|
||||||
|
"grey92":"ebebeb",
|
||||||
|
"gray93":"ededed",
|
||||||
|
"grey93":"ededed",
|
||||||
|
"gray94":"f0f0f0",
|
||||||
|
"grey94":"f0f0f0",
|
||||||
|
"gray95":"f2f2f2",
|
||||||
|
"grey95":"f2f2f2",
|
||||||
|
"gray96":"f5f5f5",
|
||||||
|
"grey96":"f5f5f5",
|
||||||
|
"gray97":"f7f7f7",
|
||||||
|
"grey97":"f7f7f7",
|
||||||
|
"gray98":"fafafa",
|
||||||
|
"grey98":"fafafa",
|
||||||
|
"gray99":"fcfcfc",
|
||||||
|
"grey99":"fcfcfc",
|
||||||
|
"gray100":"ffffff",
|
||||||
|
"grey100":"ffffff",
|
||||||
|
"dark grey":"a9a9a9",
|
||||||
|
"darkgrey":"a9a9a9",
|
||||||
|
"dark gray":"a9a9a9",
|
||||||
|
"darkgray":"a9a9a9",
|
||||||
|
"dark blue":"00008b",
|
||||||
|
"darkblue":"00008b",
|
||||||
|
"dark cyan":"008b8b",
|
||||||
|
"darkcyan":"008b8b",
|
||||||
|
"dark magenta":"8b008b",
|
||||||
|
"darkmagenta":"8b008b",
|
||||||
|
"dark red":"8b0000",
|
||||||
|
"darkred":"8b0000",
|
||||||
|
"light green":"90ee90",
|
||||||
|
"lightgreen":"90ee90",
|
||||||
|
"none":"000000"
|
||||||
|
}
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) != 2:
|
||||||
|
print("Use: py xpmconv.py |filename.xpm|")
|
||||||
|
exit(1)
|
||||||
|
if ".xpm" not in sys.argv[1]:
|
||||||
|
print("not an xpm file")
|
||||||
|
exit(1)
|
||||||
|
with open(sys.argv[1], "r") as f:
|
||||||
|
oldxpm = f.readlines()[3:]
|
||||||
|
fname = (sys.argv[1])[:-3] + "xpm42"
|
||||||
|
newxpm42 = open(fname, "w")
|
||||||
|
newxpm42.write("!XPM42\n")
|
||||||
|
cpp = int(oldxpm[0].split()[3])
|
||||||
|
newxpm42.write(oldxpm[0][1:-3] + "c\n")
|
||||||
|
oldxpm.pop(0)
|
||||||
|
prev = 0
|
||||||
|
for l in oldxpm:
|
||||||
|
if "/* pixels */" in l:
|
||||||
|
break
|
||||||
|
temp = l[1:-3] + "FF" + "\n"
|
||||||
|
out = temp[:cpp]
|
||||||
|
out = out + temp[(cpp+2):]
|
||||||
|
if "#" not in out[2:]:
|
||||||
|
repcol = out[cpp+1:]
|
||||||
|
temp = repcol[:-3].lower()
|
||||||
|
repcol = colours[repcol[:-3].lower()]
|
||||||
|
out = out[:cpp+1] + "#" + repcol.upper() + "FF\n"
|
||||||
|
if temp == "none":
|
||||||
|
out = out[:-3] + "00\n"
|
||||||
|
newxpm42.write(out)
|
||||||
|
prev += 1
|
||||||
|
oldxpm = oldxpm[prev + 1:]
|
||||||
|
for i, l in enumerate(oldxpm):
|
||||||
|
if "};" in oldxpm[i + 1]:
|
||||||
|
temp = l[1:-2] + "\n"
|
||||||
|
newxpm42.write(temp)
|
||||||
|
break
|
||||||
|
temp = l[1:-3] + "\n"
|
||||||
|
newxpm42.write(temp)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
Loading…
Reference in New Issue
Block a user