Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Latest CMakefile.txt for all platforms #6

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -2,11 +2,52 @@
sfml-widgets-demo

# Lib
*.lai
*.la
*.a
*.lib

# Compiled Dynamic libraries
*.so
*.dylib
*.dl

# Compilation files
*.slo
*.lo
*.o
*.obj

# Executables
*.exe
*.out
*.app
*.zip
*.rar
/cmake-build-*/
**/.DS_Store

# Code::Blocks
sfml-widgets.layout
sfml-widgets.depend

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
[Oo]ut/

# Visual Studio
.vs/
.vscode/

# Clion
*.iml
.idea/
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"githubPullRequests.ignoredPullRequestBranches": [
"master"
]
}
86 changes: 86 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
cmake_minimum_required(VERSION 3.20 FATAL_ERROR)
project(sfml-widgets VERSION 1.1.0)

# ##############################################################################
# Option Setting
option(ENABLE_DEMO "build demo program.(Default:ON)" ON)
set(DEMO_EXE "demo_widgets")

# ##############################################################################
# HINT: Tell CMake which directory you installed SFML libs
###############################################################################
##### (WINDOWS)
# set(SFML_HOME "C:/SFML/SFML-2.6.1")
##### (MACOS)
# set(SFML_HOME "/Library/Frameworks/SFML.framework/")

set(ENABLE_DEMO TRUE)

# FIND SFML precompiled libs & headers
##############################################
# set(SFML_DIR ${SFML_HOME}/lib/cmake/SFML)
find_package(SFML 2.5 REQUIRED COMPONENTS "graphics" "window" "system")
find_package(OpenGL REQUIRED)

# ##############################################################################
# Configure general build settings
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
if(NOT APPLE)
set(SFML_STATIC_LIBRARIES TRUE)
endif()

# ##############################################################################
# Configure build for SFML Widgets library
file(GLOB_RECURSE SFML_WIDGETS_SRC src/Gui/*.cpp)
add_library(sfml-widgets ${SFML_WIDGETS_SRC})
target_link_libraries(sfml-widgets PUBLIC sfml-graphics sfml-window sfml-system)
target_include_directories(sfml-widgets PUBLIC ${CMAKE_SOURCE_DIR}/src/)

# show warnings (depending on C++ compiler)
if(MSVC)
target_compile_options(${CMAKE_PROJECT_NAME} PUBLIC /W4)
else()
target_compile_options(${CMAKE_PROJECT_NAME} PUBLIC -Wall -Wextra)
endif()

# ##############################################################################
# Configure build for Sample program
############################ START OF DEMO ###############################

if(ENABLE_DEMO)
file(GLOB DEMO_SRC demo/*.cpp demo/*.mm)

if(WIN32)
add_executable(${DEMO_EXE} WIN32 ${DEMO_SRC} ${CMAKE_SOURCE_DIR}/demo/resources/win-icon.rc)
target_link_libraries(${DEMO_EXE} PRIVATE sfml-widgets sfml-main OpenGL::GL sfml-graphics
sfml-window sfml-system)

elseif(APPLE)
include(${CMAKE_SOURCE_DIR}/apple_cmake/MacBundle.cmake)
find_library(FOUNDATION_FRAMEWORK Foundation)
target_link_libraries(${DEMO_EXE} PRIVATE sfml-widgets OpenGL::GL sfml-graphics sfml-window
sfml-system ${FOUNDATION_FRAMEWORK})
else()
add_executable(${DEMO_EXE} ${DEMO_SRC})
target_link_libraries(${DEMO_EXE} PRIVATE sfml-widgets OpenGL::GL sfml-graphics sfml-window
sfml-system)
endif(WIN32)


# INCLUDE SFML Headers
####################################################
# include_directories(${SFML_HOME}/include)

# COPY RESOURCES TO BUILD FOLDER (Windows & Linux)
#####################################################
if(NOT APPLE)
add_custom_command(TARGET ${DEMO_EXE}
POST_BUILD COMMAND
${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/demo/resources
$<TARGET_FILE_DIR:${DEMO_EXE}>/resources)
endif()
endif(ENABLE_DEMO)
############################ END OF DEMO PROGRAM ###############################


38 changes: 0 additions & 38 deletions Makefile

This file was deleted.

53 changes: 47 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -12,11 +12,47 @@ A simple GUI module for SFML.
- Author: Alexandre Bodelot <[email protected]>
- License: [MIT License](http://opensource.org/licenses/MIT) (See LICENSE file)

Run `make` to build the library (`lib/libsfml-widgets.a`) and the demo program.
## Requirements:
- [Download SFML 2.6.x](https://www.sfml-dev.org/download.php) for your platform
- Latest [CMake Installer](https://cmake.org/download/) - version 3.20 or higher

### Windows:
- Visual Studio 2017 or later (select complete "**Desktop C++ Development**" workload)
- CMake for Visual Studio (download using Visual Studio installer).

### MacOS
- XCode latest with MacOS SDK.
- Follow [official guide](https://www.sfml-dev.org/tutorials/2.6/start-osx.php) on installing SFML on MacOS
- Extra Apple Developer Tools. After Xcode installs, run this in Terminal:
```bash
sudo xcode-select --install
```
- After CMake GUI installs on your Mac, make sure to add its CLI to PATH:
```bash
sudo "/Applications/CMake.app/Contents/bin/cmake-gui" --install
```

### Linux Desktop
- Use your package manager (`apt-get` or `yum`) to download SFML dev dependencies listed [in official docs](https://www.sfml-dev.org/tutorials/2.6/compile-with-cmake.php#installing-dependencies)

## Building locally

- On Windows, open this project in Visual Studio 2022 or later, choose "Release" or "Debug" from top toolbar. Then click "Build" > "Build All".
- If using CMake GUI (all platforms), set "Source Folder" to this project root. Then set "Build Folder" to new _relative_ folder `/build` or `/out`. See image below. Then click "Configure", choose **Unix Makefiles**, then click Generate. Finally, open build folder, then run `make all` in Terminal.

![cmake_screenshot](doc/cmake_gui.png)

- Alternatively, you can use the CMake CLI on your Terminal:

```bash
mkdir build
cd build
cmake . .
cmake --build . --config Release --target all
```

You can then run the demo: `./sfml-widgets-demo`

## Setup
## How to use the library

1. Load resources (font, spritesheet) in static class `gui::Theme`
2. Use `gui::Menu` to create a new sfml-widgets menu. It needs to be connected to your SFML render window, which is given to the constructor.
@@ -32,12 +68,15 @@ Minimal example:
int main()
{
sf::RenderWindow app(sf::VideoMode(800, 600), "SFML Widgets", sf::Style::Close);
//Set FPS limit
//app.setFramerateLimit(60);

// Declare menu
gui::Menu menu(app);

gui::Theme::loadFont("demo/tahoma.ttf");
gui::Theme::loadTexture("demo/texture-default.png");
gui::Theme::loadFont("resources/tahoma.ttf");
gui::Theme::loadTexture("resources/texture-default.png");

// Create some button widget
gui::Button* button = new gui::Button("My button");
@@ -74,12 +113,14 @@ int main()
app.display();
}

return 0;
return EXIT_SUCCESS;
}
```

`demo/demo.cpp` conains a more complex example, featuring all widgets.

![demo_screenshot](doc/demo_screenshot.png)

## Widgets

### `gui::Button`
30 changes: 30 additions & 0 deletions apple_cmake/MacBundle.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# app icon
set(MACOSX_BUNDLE_ICON_FILE "SfmlWidgets.icns")
set(application_icon "${CMAKE_SOURCE_DIR}/demo/resources/${MACOSX_BUNDLE_ICON_FILE}")
set_source_files_properties(${application_icon}
PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")

# images and fonts
file(GLOB_RECURSE my_images "${CMAKE_SOURCE_DIR}/demo/resources/*")
foreach(FILE ${my_images})
file(RELATIVE_PATH NEW_FILE "${CMAKE_SOURCE_DIR}/" ${FILE})
get_filename_component(NEW_FILE_PATH ${NEW_FILE} DIRECTORY)
set_source_files_properties(${FILE} PROPERTIES MACOSX_PACKAGE_LOCATION
"Resources/${NEW_FILE_PATH}")
endforeach()

add_executable(${DEMO_EXE} MACOSX_BUNDLE
${DEMO_SRC} "${my_images}")

set_target_properties(
${DEMO_EXE}
PROPERTIES BUNDLE TRUE
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ""
XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO"
XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/../Frameworks"
MACOSX_BUNDLE_BUNDLE_NAME "${DEMO_EXE}"
MACOSX_BUNDLE_GUI_IDENTIFIER "com.alexandre.bodelot.${DEMO_EXE}"
MACOSX_BUNDLE_COPYRIGHT "(c) 2021, Alexandre Bodelot"
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION}
RESOURCE "${my_images}")
4 changes: 4 additions & 0 deletions apple_cmake/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
## What's this file for?

This contains specific CMake instructions to build MacOS GUI `.app` Bundle for the demo. It embeds the icon to the app bundle. It also copies all assets/resources into the Bundle at build time. It additionally adds an important `Info.plist` file which contains metadata about the application.

11 changes: 11 additions & 0 deletions demo/ResourcePath.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// for Windows and Linux OS. Helper to load assets

#ifndef __APPLE__
#include "ResourcePath.hpp"

std::string chk::getResourcePath(const std::string& relativePath)
{
return "resources/" + relativePath;
}

#endif
16 changes: 16 additions & 0 deletions demo/ResourcePath.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <iostream>
#include <string>

namespace chk
{
/**
* \brief Get absolute path of file specified
* \param relativePath file relative to `Resources/` directory
* \return The absolute file path
*/
std::string getResourcePath(const std::string &relativePath);
} // namespace chk
16 changes: 16 additions & 0 deletions demo/ResourcePath.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include "ResourcePath.hpp"

#ifdef __APPLE__
#import <Foundation/Foundation.h>
std::string chk::getResourcePath(const std::string& relativePath) {
NSBundle* mainBundle = [NSBundle mainBundle];
NSString* resourcePath = [mainBundle pathForResource:@(relativePath.c_str()) ofType:nil];

if (resourcePath == nil) {
std::cerr << "Error: File '" << relativePath << "' not found." << std::endl;
return "";
}

return [resourcePath UTF8String];
}
#endif
129 changes: 67 additions & 62 deletions demo/demo.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "Gui/Theme.hpp"
#include "Gui/Gui.hpp"
#include <SFML/Graphics.hpp>
#include "ResourcePath.hpp"


sf::Color hex2color(const std::string& hexcolor)
@@ -29,15 +30,9 @@ struct Theme

int main()
{
Theme defaultTheme = {
hex2color("#dddbde"),
"demo/texture-default.png"
};
Theme defaultTheme = {hex2color("#dddbde"), chk::getResourcePath("texture-default.png")};

Theme win98Theme = {
hex2color("#d4d0c8"),
"demo/texture-win98.png"
};
Theme win98Theme = {hex2color("#d4d0c8"), chk::getResourcePath("texture-win98.png")};

// Create the main window
sf::RenderWindow app(sf::VideoMode(800, 600), "SFML Widgets", sf::Style::Close);
@@ -46,10 +41,10 @@ int main()
gui::Menu menu(app);
menu.setPosition(10, 10);

gui::Theme::loadFont("demo/tahoma.ttf");
gui::Theme::loadFont(chk::getResourcePath("tahoma.ttf"));
gui::Theme::loadTexture(defaultTheme.texturePath);
gui::Theme::textSize = 11;
gui::Theme::click.textColor = hex2color("#191B18");
gui::Theme::click.textColor = hex2color("#191B18");
gui::Theme::click.textColorHover = hex2color("#191B18");
gui::Theme::click.textColorFocus = hex2color("#000");
gui::Theme::input.textColor = hex2color("#000");
@@ -70,10 +65,13 @@ int main()
// Textbox
gui::TextBox* textbox = new gui::TextBox();
textbox->setText("Hello world!");
textbox->setCallback([&]() {
text.setString(textbox->getText());
text.setOrigin(text.getLocalBounds().width / 2, text.getLocalBounds().height / 2);
});
textbox->setCallback(
[&]()
{
text.setString(textbox->getText());
text.setOrigin(text.getLocalBounds().width / 2, text.getLocalBounds().height / 2);
}
);
textbox->setPlaceholder("Type something!");
form->addRow("Text", textbox);

@@ -89,26 +87,32 @@ int main()
gui::ProgressBar* pbarRotation3 = new gui::ProgressBar(200.f, gui::Horizontal, gui::LabelOutside);

sliderRotation->setStep(1);
sliderRotation->setCallback([&]() {
text.setRotation(sliderRotation->getValue() * 360 / 100.f);
pbarRotation1->setValue(sliderRotation->getValue());
pbarRotation2->setValue(sliderRotation->getValue());
pbarRotation3->setValue(sliderRotation->getValue());
});
sliderRotation->setCallback(
[&]()
{
text.setRotation(sliderRotation->getValue() * 360 / 100.f);
pbarRotation1->setValue(sliderRotation->getValue());
pbarRotation2->setValue(sliderRotation->getValue());
pbarRotation3->setValue(sliderRotation->getValue());
}
);
form->addRow("Rotation", sliderRotation);

// Slider + ProgressBar for scale
gui::Slider* sliderScale = new gui::Slider();
gui::ProgressBar* pbarScale1 = new gui::ProgressBar(100, gui::Vertical, gui::LabelNone);
gui::ProgressBar* pbarScale2 = new gui::ProgressBar(100, gui::Vertical, gui::LabelOver);
gui::ProgressBar* pbarScale3 = new gui::ProgressBar(100, gui::Vertical, gui::LabelOutside);
sliderScale->setCallback([&]() {
float scale = 1 + sliderScale->getValue() * 2 / 100.f;
text.setScale(scale, scale);
pbarScale1->setValue(sliderScale->getValue());
pbarScale2->setValue(sliderScale->getValue());
pbarScale3->setValue(sliderScale->getValue());
});
sliderScale->setCallback(
[&]()
{
float scale = 1 + sliderScale->getValue() * 2 / 100.f;
text.setScale(scale, scale);
pbarScale1->setValue(sliderScale->getValue());
pbarScale2->setValue(sliderScale->getValue());
pbarScale3->setValue(sliderScale->getValue());
}
);
form->addRow("Scale", sliderScale);

// OptionsBox for color
@@ -118,32 +122,36 @@ int main()
opt->addItem("Green", sf::Color::Green);
opt->addItem("Yellow", sf::Color::Yellow);
opt->addItem("White", sf::Color::White);
opt->setCallback([&]() {
text.setFillColor(opt->getSelectedValue());
});
opt->setCallback([&]() { text.setFillColor(opt->getSelectedValue()); });
form->addRow("Color", opt);

// Checbkox
gui::CheckBox* checkboxBold = new gui::CheckBox();
checkboxBold->setCallback([&]() {
int style = text.getStyle();
if (checkboxBold->isChecked())
style |= sf::Text::Bold;
else
style &= ~sf::Text::Bold;
text.setStyle(style);
});
checkboxBold->setCallback(
[&]()
{
int style = text.getStyle();
if (checkboxBold->isChecked())
style |= sf::Text::Bold;
else
style &= ~sf::Text::Bold;
text.setStyle(style);
}
);
form->addRow("Bold text", checkboxBold);

gui::CheckBox* checkboxUnderlined = new gui::CheckBox();
checkboxUnderlined->setCallback([&]() {
int style = text.getStyle();
if (checkboxUnderlined->isChecked())
style |= sf::Text::Underlined;
else
style &= ~sf::Text::Underlined;
text.setStyle(style);
});
checkboxUnderlined->setCallback(
[&]()
{
int style = text.getStyle();
if (checkboxUnderlined->isChecked())
style |= sf::Text::Underlined;
else
style &= ~sf::Text::Underlined;
text.setStyle(style);
}
);
form->addRow("Underlined text", checkboxUnderlined);

// Progress bar
@@ -162,7 +170,7 @@ int main()

// Custom button
sf::Texture imgbutton;
imgbutton.loadFromFile("demo/themed-button.png");
imgbutton.loadFromFile(chk::getResourcePath("themed-button.png"));

gui::SpriteButton* customButton = new gui::SpriteButton(imgbutton, "Play");
customButton->setTextSize(20);
@@ -174,11 +182,14 @@ int main()
gui::OptionsBox<Theme>* themeBox = new gui::OptionsBox<Theme>();
themeBox->addItem("Windows 98", win98Theme);
themeBox->addItem("Default", defaultTheme);
themeBox->setCallback([&]() {
const Theme& theme = themeBox->getSelectedValue();
gui::Theme::loadTexture(theme.texturePath);
gui::Theme::windowBgColor = theme.backgroundColor;
});
themeBox->setCallback(
[&]()
{
const Theme& theme = themeBox->getSelectedValue();
gui::Theme::loadTexture(theme.texturePath);
gui::Theme::windowBgColor = theme.backgroundColor;
}
);
vbox->add(themeBox);

// Textbox
@@ -187,9 +198,7 @@ int main()
textbox3->setText("My Button");
textbox3->setPlaceholder("Button label");
hbox2->add(textbox3);
hbox2->addButton("Create button", [&]() {
vbox->add(new gui::Button(textbox3->getText()));
});
hbox2->addButton("Create button", [&]() { vbox->add(new gui::Button(textbox3->getText())); });

// Small progress bar
gui::HBoxLayout* hbox3 = vbox->addHBoxLayout();
@@ -198,17 +207,13 @@ int main()
hbox3->add(pbar);

gui::Slider* vslider = new gui::Slider(100, gui::Vertical);
vslider->setCallback([&]() {
pbar->setValue(vslider->getValue());
});
vslider->setCallback([&]() { pbar->setValue(vslider->getValue()); });
hbox->add(vslider);

menu.addButton("Quit", [&]() {
app.close();
});
menu.addButton("Quit", [&]() { app.close(); });

sf::Texture texture;
texture.loadFromFile("demo/sfml.png");
texture.loadFromFile(chk::getResourcePath("sfml.png"));

sf::Sprite sprite(texture);
sprite.setOrigin(texture.getSize().x / 2, texture.getSize().y / 2);
Binary file added demo/resources/SfmlWidgets.icns
Binary file not shown.
File renamed without changes
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes
Binary file added demo/resources/win-icon.ico
Binary file not shown.
1 change: 1 addition & 0 deletions demo/resources/win-icon.rc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
IDI_ICON1 ICON DISCARDABLE "win-icon.ico"
Binary file added doc/cmake_gui.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/demo_screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.