From d9ca7a386608d6d8d8b00a2e0ddef7d7f003a4c4 Mon Sep 17 00:00:00 2001 From: Alison Watson Date: Wed, 15 May 2019 15:54:35 -0400 Subject: [PATCH] initial qt gui test --- CMakeLists.txt | 47 + source/tycho-qt/main.cc | 18 + source/tycho-qt/mainwindow.cc | 16 + source/tycho-qt/mainwindow.h | 24 + source/tycho-qt/mainwindow.ui | 24 + source/tycho/Cargo.toml | 20 +- source/tycho/build.rs | 48 - source/tycho/data/resources.xml | 19 - source/tycho/data/styles.css | 1 - source/tycho/data/ui.xml | 1378 ----------------------------- source/tycho/interfaces.rs | 9 - source/tycho/interfaces/cairo.rs | 156 ---- source/tycho/interfaces/editor.rs | 49 - source/tycho/interfaces/glib.rs | 113 --- source/tycho/lib.rs | 7 + source/tycho/main.rs | 374 -------- 16 files changed, 141 insertions(+), 2162 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 source/tycho-qt/main.cc create mode 100644 source/tycho-qt/mainwindow.cc create mode 100644 source/tycho-qt/mainwindow.h create mode 100644 source/tycho-qt/mainwindow.ui delete mode 100644 source/tycho/build.rs delete mode 100644 source/tycho/data/resources.xml delete mode 100644 source/tycho/data/styles.css delete mode 100644 source/tycho/data/ui.xml delete mode 100644 source/tycho/interfaces.rs delete mode 100644 source/tycho/interfaces/cairo.rs delete mode 100644 source/tycho/interfaces/editor.rs delete mode 100644 source/tycho/interfaces/glib.rs create mode 100644 source/tycho/lib.rs delete mode 100644 source/tycho/main.rs diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..6959fc3 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,47 @@ +cmake_minimum_required(VERSION 3.14) +project(maraiah-tycho CXX) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) +set(THREADS_PREFER_PTHREAD_FLAG ON) +set(RS_DIR "${CMAKE_BINARY_DIR}/maraiah-tycho-lib") +set(RS_OUT "${RS_DIR}/build") +set(RS_LIB "${RS_OUT}/debug/libtycho.a") + +find_package(Threads REQUIRED) +find_package(Qt5Widgets CONFIG REQUIRED) + +add_executable( + maraiah-tycho + WIN32 + source/tycho-qt/main.cc + source/tycho-qt/mainwindow.cc + source/tycho-qt/mainwindow.h + source/tycho-qt/mainwindow.ui +) + +add_custom_target( + maraiah-tycho-lib ALL + BYPRODUCTS "${RS_LIB}" + COMMAND cargo build -p maraiah-tycho --target-dir "${RS_OUT}" + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" + COMMENT "Building Rust library" +) + +set_target_properties( + maraiah-tycho + PROPERTIES + CXX_STANDARD 17 + CXX_STANDARD_REQUIRED ON +) + +target_link_libraries( + maraiah-tycho + "${RS_LIB}" + Threads::Threads + ${CMAKE_DL_LIBS} + Qt5::Widgets +) + +## EOF diff --git a/source/tycho-qt/main.cc b/source/tycho-qt/main.cc new file mode 100644 index 0000000..38a869b --- /dev/null +++ b/source/tycho-qt/main.cc @@ -0,0 +1,18 @@ +#include "mainwindow.h" +#include +#include + +extern "C" void test_fn(); + +int main(int argc, char *argv[]) +{ + puts("hello, world"); + test_fn(); + + QApplication a(argc, argv); + MainWindow w; + w.show(); + return a.exec(); +} + +// EOF diff --git a/source/tycho-qt/mainwindow.cc b/source/tycho-qt/mainwindow.cc new file mode 100644 index 0000000..8b3204a --- /dev/null +++ b/source/tycho-qt/mainwindow.cc @@ -0,0 +1,16 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow) +{ + ui->setupUi(this); +} + +MainWindow::~MainWindow() +{ + delete ui; +} + +// EOF diff --git a/source/tycho-qt/mainwindow.h b/source/tycho-qt/mainwindow.h new file mode 100644 index 0000000..8bc3d6a --- /dev/null +++ b/source/tycho-qt/mainwindow.h @@ -0,0 +1,24 @@ +#pragma once +#ifndef tycho_qt__mainwindow_h +#define tycho_qt__mainwindow_h + +#include + +namespace Ui +{ + class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = nullptr); + ~MainWindow(); + +private: + Ui::MainWindow *ui; +}; + +#endif diff --git a/source/tycho-qt/mainwindow.ui b/source/tycho-qt/mainwindow.ui new file mode 100644 index 0000000..8e8a033 --- /dev/null +++ b/source/tycho-qt/mainwindow.ui @@ -0,0 +1,24 @@ + + MainWindow + + + + 0 + 0 + 400 + 300 + + + + MainWindow + + + + + + + + + + + diff --git a/source/tycho/Cargo.toml b/source/tycho/Cargo.toml index 4ad723c..ff6b0a5 100644 --- a/source/tycho/Cargo.toml +++ b/source/tycho/Cargo.toml @@ -4,22 +4,12 @@ version = "0.1.0" authors = ["Alison Sanderson "] description = "Tycho map editor." edition = "2018" -build = "build.rs" [dependencies] -atk-sys = "0.8" -cairo-sys-rs = "0.8" -gdk-pixbuf-sys = "0.8" -gdk-sys = "0.8" -gio-sys = "0.8" -glib-sys = "0.8" -gobject-sys = "0.8" -gtk-sys = {version = "0.8", features = ["v3_16"]} -maraiah = {path = "../.."} -memmap = "0.7" -pango-sys = "0.8" -pangocairo-sys = "0.9" +maraiah = {path = "../.."} +memmap = "0.7" -[[bin]] +[lib] name = "tycho" -path = "main.rs" +path = "lib.rs" +crate-type = ["staticlib"] diff --git a/source/tycho/build.rs b/source/tycho/build.rs deleted file mode 100644 index 58aab15..0000000 --- a/source/tycho/build.rs +++ /dev/null @@ -1,48 +0,0 @@ -use std::{env, fs, io, path::Path, process::Command}; - -fn io_err(st: &'static str) -> io::Error -{ - io::Error::new(io::ErrorKind::Other, st) -} - -fn traverse_dir(path: &Path) -> io::Result<()> -{ - for ent in fs::read_dir(path)? { - let path = ent?.path(); - - if path.is_dir() { - traverse_dir(&path)?; - } else { - if let Some(path) = path.to_str() { - println!("cargo:rerun-if-changed={}", path); - } else { - return Err(io_err("failed to convert path")); - } - } - } - - Ok(()) -} - -fn main() -> io::Result<()> -{ - let out_file = env::var("OUT_DIR").unwrap(); - let out_file = format!("--target={}/resources", out_file); - - // traverse each file in the data directory, because cargo won't do this - traverse_dir(Path::new("data"))?; - - let o = Command::new("glib-compile-resources").arg("data/resources.xml") - .arg(out_file) - .output() - .unwrap(); - - if !o.status.success() { - dbg!(o); - Err(io_err("failed to compile resources")) - } else { - Ok(()) - } -} - -// EOF diff --git a/source/tycho/data/resources.xml b/source/tycho/data/resources.xml deleted file mode 100644 index 1e4c785..0000000 --- a/source/tycho/data/resources.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - data/misc/tycho1.png - data/misc/tycho2.png - data/styles.css - data/ui.xml - - - - data/color/polygons.png - data/color/lines.png - data/color/points.png - - - data/color/map.png - - diff --git a/source/tycho/data/styles.css b/source/tycho/data/styles.css deleted file mode 100644 index 6a974a7..0000000 --- a/source/tycho/data/styles.css +++ /dev/null @@ -1 +0,0 @@ -/* EOF */ diff --git a/source/tycho/data/ui.xml b/source/tycho/data/ui.xml deleted file mode 100644 index 1dfc46c..0000000 --- a/source/tycho/data/ui.xml +++ /dev/null @@ -1,1378 +0,0 @@ - - - - - - 100 - 1 - 10 - - - 100 - 1 - 10 - - - 65535 - 1 - 10 - - - False - True - dialog - Tycho Map Editor - By Alison Sanderson. Public domain. - greetigs i am tico the of superior ai to durdumbal go shoot my soldiers because its funny or ill put you in space - Home Page - To the extent possible under law, I, Alison Sanderson, have waived all -copyright and related or neighboring rights to this Document as described by -the Creative Commons Zero license as follows: - -Creative Commons Legal Code - -CC0 1.0 Universal - - CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE - LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN - ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS - INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES - REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS - PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM - THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED - HEREUNDER. - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer -exclusive Copyright and Related Rights (defined below) upon the creator -and subsequent owner(s) (each and all, an "owner") of an original work of -authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for -the purpose of contributing to a commons of creative, cultural and -scientific works ("Commons") that the public can reliably and without fear -of later claims of infringement build upon, modify, incorporate in other -works, reuse and redistribute as freely as possible in any form whatsoever -and for any purposes, including without limitation commercial purposes. -These owners may contribute to the Commons to promote the ideal of a free -culture and the further production of creative, cultural and scientific -works, or to gain reputation or greater distribution for their Work in -part through the use and efforts of others. - -For these and/or other purposes and motivations, and without any -expectation of additional consideration or compensation, the person -associating CC0 with a Work (the "Affirmer"), to the extent that he or she -is an owner of Copyright and Related Rights in the Work, voluntarily -elects to apply CC0 to the Work and publicly distribute the Work under its -terms, with knowledge of his or her Copyright and Related Rights in the -Work and the meaning and intended legal effect of CC0 on those rights. - -1. Copyright and Related Rights. A Work made available under CC0 may be -protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not -limited to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, - communicate, and translate a Work; - ii. moral rights retained by the original author(s) and/or performer(s); -iii. publicity and privacy rights pertaining to a person's image or - likeness depicted in a Work; - iv. rights protecting against unfair competition in regards to a Work, - subject to the limitations in paragraph 4(a), below; - v. rights protecting the extraction, dissemination, use and reuse of data - in a Work; - vi. database rights (such as those arising under Directive 96/9/EC of the - European Parliament and of the Council of 11 March 1996 on the legal - protection of databases, and under any national implementation - thereof, including any amended or successor version of such - directive); and -vii. other similar, equivalent or corresponding rights throughout the - world based on applicable law or treaty, and any national - implementations thereof. - -2. Waiver. To the greatest extent permitted by, but not in contravention -of, applicable law, Affirmer hereby overtly, fully, permanently, -irrevocably and unconditionally waives, abandons, and surrenders all of -Affirmer's Copyright and Related Rights and associated claims and causes -of action, whether now known or unknown (including existing as well as -future claims and causes of action), in the Work (i) in all territories -worldwide, (ii) for the maximum duration provided by applicable law or -treaty (including future time extensions), (iii) in any current or future -medium and for any number of copies, and (iv) for any purpose whatsoever, -including without limitation commercial, advertising or promotional -purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each -member of the public at large and to the detriment of Affirmer's heirs and -successors, fully intending that such Waiver shall not be subject to -revocation, rescission, cancellation, termination, or any other legal or -equitable action to disrupt the quiet enjoyment of the Work by the public -as contemplated by Affirmer's express Statement of Purpose. - -3. Public License Fallback. Should any part of the Waiver for any reason -be judged legally invalid or ineffective under applicable law, then the -Waiver shall be preserved to the maximum extent permitted taking into -account Affirmer's express Statement of Purpose. In addition, to the -extent the Waiver is so judged Affirmer hereby grants to each affected -person a royalty-free, non transferable, non sublicensable, non exclusive, -irrevocable and unconditional license to exercise Affirmer's Copyright and -Related Rights in the Work (i) in all territories worldwide, (ii) for the -maximum duration provided by applicable law or treaty (including future -time extensions), (iii) in any current or future medium and for any number -of copies, and (iv) for any purpose whatsoever, including without -limitation commercial, advertising or promotional purposes (the -"License"). The License shall be deemed effective as of the date CC0 was -applied by Affirmer to the Work. Should any part of the License for any -reason be judged legally invalid or ineffective under applicable law, such -partial invalidity or ineffectiveness shall not invalidate the remainder -of the License, and in such case Affirmer hereby affirms that he or she -will not (i) exercise any of his or her remaining Copyright and Related -Rights in the Work or (ii) assert any associated claims and causes of -action with respect to the Work, in either case contrary to Affirmer's -express Statement of Purpose. - -4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, - surrendered, licensed or otherwise affected by this document. - b. Affirmer offers the Work as-is and makes no representations or - warranties of any kind concerning the Work, express, implied, - statutory or otherwise, including without limitation warranties of - title, merchantability, fitness for a particular purpose, non - infringement, or the absence of latent or other defects, accuracy, or - the present or absence of errors, whether or not discoverable, all to - the greatest extent permissible under applicable law. - c. Affirmer disclaims responsibility for clearing rights of other persons - that may apply to the Work or any use thereof, including without - limitation any person's Copyright and Related Rights in the Work. - Further, Affirmer disclaims responsibility for obtaining any necessary - consents, permissions or other rights required for any use of the - Work. - d. Affirmer understands and acknowledges that Creative Commons is not a - party to this document and has no duty or obligation with respect to - this CC0 or use of the Work. - - image-loading - custom - - - - - - False - vertical - 2 - - - False - end - - - False - False - 0 - - - - - - - - - - About Screen - The about screen for Tycho. - dialog - - - - - True - False - 24 - tycho-lines - - - True - False - 24 - tycho-points - - - True - False - 24 - tycho-polys - - - False - Tycho - False - 120 - 250 - - - - - - True - False - ttb - - - True - False - _File - True - - - True - False - - - True - False - Create a new project. - _New Project - True - - - - - True - False - Opens any type of project file. - _Open - True - - - - - True - False - Saves the currently open project. - _Save - True - - - - - True - False - - - - - True - False - Quit the application. - _Quit - True - - - - - - - - - True - False - _View - True - - - True - False - - - True - False - Opens the map view window. - Show _Map View - True - - - - - True - False - Opens the map toolbox window. - Show Map _Tools - True - - - - - True - False - Show Map _Properties - True - - - - - - - - - True - False - - - - - True - False - True - _Info - True - - - True - False - - - True - False - Opens a window with information about this program. - _About - True - - - - - - - - - - - False - 5 - Map Properties - win-main - win-main - - - - - - True - False - vertical - 5 - - - True - False - 0 - none - - - True - False - 12 - - - True - True - The name of the map. Unicode symbols that are supported by the Mac OS Roman encoding are converted automatically when saved. - - - - - - - True - False - Map Name - - - - - False - True - 0 - - - - - True - False - 5 - - - True - False - vertical - 5 - True - - - True - False - 0 - none - - - True - False - 0 - 0 - 0 - 12 - - - True - False - The texture collection to use for the map. This is one of five bitmap collections stored in the Shapes file. - 0 - - Water - Lava - Sewage - Jjaro - Pfhor - - - - - - - - True - False - Texture Set - - - - - False - True - 0 - - - - - True - False - 0 - none - - - True - False - 0 - 0 - 0 - 12 - - - True - False - The sky to display on sides which are marked as "Landscape." This is the sole bitmap of one of four collections in the Shapes file. - 0 - - Lh'owon Day - Lh'owon Night - Moon - Space - - - - - - - - True - False - Landscape - - - - - False - True - 1 - - - - - True - True - 0 - - - - - True - False - These flags mark which game modes this map can be used in. - 0 - in - - - True - False - 12 - - - True - False - - - Solo - True - True - False - The map can be played in single-player. - True - True - True - - - 0 - 0 - - - - - Co-op - True - True - False - The map can be played in multi-player co-operative. - True - True - True - - - 0 - 1 - - - - - Carnage - True - True - False - The map can be played in multi-player Carnage. - True - True - True - - - 0 - 2 - - - - - KTMWTB - True - True - False - The map can be played in multi-player Kill The Man With The Ball - True - True - True - - - 0 - 3 - - - - - King Of The Hill - True - True - False - The map can be played in multi-player King of the Hill. - True - True - True - - - 1 - 0 - - - - - Defense - True - True - False - The map can be played in multi-player Defense. - True - True - True - - - 1 - 1 - - - - - Rugby - True - True - False - The map can be played in multi-player Rugby. - True - True - True - - - 1 - 2 - - - - - Capture The Flag - True - True - False - The map can be played in multi-player Capture The Flag. - True - True - True - - - 1 - 3 - - - - - - - - - True - False - Entry Flags - - - - - True - True - 1 - - - - - True - True - 1 - - - - - True - False - 10 - - - True - False - These flags are used to determine what the player must do to get success conditions in computer terminals. - 0 - in - - - True - False - vertical - - - True - False - Vanilla - - - False - True - 0 - - - - - Extermination - True - True - False - Player must kill all monsters on the map, with an error threshold of 8 aliens maximum. - True - - - False - True - 1 - - - - - Exploration - True - True - False - Player must explore all marked polygons. - True - - - False - True - 2 - - - - - Retrieval - True - True - False - Player must grab all items marked items. - True - - - False - True - 3 - - - - - Repair - True - True - False - Player must flip all marked switches. - True - - - False - True - 4 - - - - - Rescue - True - True - False - Player must keep 50% or more civilians alive. - True - - - False - True - 5 - - - - - True - False - Aleph One - - - False - True - 6 - - - - - M1 Exploration - True - True - False - The same as Exploration, but you only need to look at each marked polygon, not actually walk in them. - True - - - False - True - 7 - - - - - M1 Rescue - True - True - False - The same as Rescue, but uses the Marathon 1 class numbers. - True - - - False - True - 8 - - - - - M1 Repair - True - True - False - The same as Repair, except it only requires that the last switch (by side index) be switched to succeed. - True - - - False - True - 9 - - - - - - - True - False - Mission Flags - - - - - True - True - 0 - - - - - True - False - These flags are used to enable various environmental effects. - 0 - in - - - True - False - vertical - - - True - False - Vanilla - - - False - True - 0 - - - - - Vacuum - True - True - False - Most weapons will not work, and the oxygen bar will deplete. - True - - - False - True - 1 - - - - - Magnetic - True - True - False - The motion sensor will behave erratically. - True - - - False - True - 2 - - - - - Rebellion - True - True - False - Items and health will be stripped, and S'pht enemies will become friendly. - True - - - False - True - 3 - - - - - Low Gravity - True - True - False - Gravity will be halved. - True - - - False - True - 4 - - - - - True - False - Aleph One - - - False - True - 5 - - - - - Marathon 1 Glue - True - True - False - Glue handles like Marathon 1. - True - - - False - True - 6 - - - - - Lava Floor - True - True - False - The floor damages you. - True - - - False - True - 7 - - - - - Rebellion (No strip) - True - True - False - The same as Rebellion, but your items and health aren't stripped. - True - - - False - True - 8 - - - - - Music - True - True - False - The map has Marathon 1-style music. - True - - - False - True - 9 - - - - - Terminals Stop Time - True - True - False - Terminals will pause the game in Solo. - True - - - False - True - 10 - - - - - M1 Monster Limits - True - True - False - Sets the monster activation limits to Marathon 1's. - True - - - False - True - 11 - - - - - M1 Weapon Differences - True - True - False - Doubles weapon pickups on Total Carnage and makes grenades low-gravity. - True - - - False - True - 12 - - - - - - - True - False - Environment Flags - - - - - True - True - 1 - - - - - True - True - 2 - - - - - True - False - 0 - in - - - True - False - 8 - - - True - False - True - - - True - False - This field is unused and must be either 0 or 1. It used to be used to give different physics to the map editor and low gravity before it was made into an environment flag. - 0 - none - - - True - False - 0 - 0 - 0 - 0 - 12 - - - True - True - 0 - True - adj-phys-id - True - True - True - - - - - - - True - False - Physics ID - - - - - False - False - 0 - - - - - True - False - This field overrides the Landscape field, and is used for Marathon 1 maps which have music. - 0 - none - - - True - False - 0 - 0 - 0 - 0 - 12 - - - True - True - This field is unused and must be either 0 or 1. It used to be used to give different physics to the map editor and low gravity before it was made into an environment flag. - 0 - True - adj-phys-id - True - True - True - - - - - - - True - False - Song ID - - - - - False - False - 1 - - - - - - - - - True - False - Advanced Options (Use at your own peril) - - - - - True - True - 3 - - - - - True - False - end - - - _Save - True - True - True - True - - - True - True - 0 - - - - - _Close - True - True - True - True - - - True - True - 1 - - - - - False - True - 4 - - - - - - - False - Tool Palette - 250 - True - win-main - win-main - - - - - - True - False - vertical - - - True - False - Geometry - - - True - False - _Points - True - img-points - - - Points Tool - The tool that modifies points in the map. - push-button - - - - - True - - - - - True - False - _Lines - True - img-lines - - - Lines Tool - The tool which modifies line segments on the map. - push-button - - - - - True - 1 - - - - - True - False - P_olygons - True - img-polys - - - Polygon Tool - The tool which modifies polygon shapes on the map. - push-button - - - - - True - 2 - - - - - Geometry Collection - All of the tools which modify map geometry. - column-header - - - - - True - - - - - - - Tycho Tool Palette - Tycho's tool palette window. - window - - - - - False - Map View - 600 - 400 - win-main - win-main - - - - - - True - True - always - always - top-right - False - - - True - False - adj-map-horz - adj-map-vert - - - True - False - - - - - - - - diff --git a/source/tycho/interfaces.rs b/source/tycho/interfaces.rs deleted file mode 100644 index 668be10..0000000 --- a/source/tycho/interfaces.rs +++ /dev/null @@ -1,9 +0,0 @@ -//! Interfaces to the system. - -pub mod cairo; -pub mod editor; -pub mod glib; - -pub use self::{cairo::*, editor::*, glib::*}; - -// EOF diff --git a/source/tycho/interfaces/cairo.rs b/source/tycho/interfaces/cairo.rs deleted file mode 100644 index ceacafb..0000000 --- a/source/tycho/interfaces/cairo.rs +++ /dev/null @@ -1,156 +0,0 @@ -//! Implemented drawing area for Cairo. - -use super::glib::*; -use cairo_sys::*; -use gdk_pixbuf_sys::*; -use gdk_sys::*; -use pango_sys::*; -use pango_cairo_sys::*; -use maraiah::{c_str, - durandal::{ffi, image::*}, - rozinante::draw}; - -/// Converts a `Color` to a `f64` triple. -fn flt_color(cr: impl Color) -> (f64, f64, f64) -{ - fn flt_color(n: u16) -> f64 {f64::from(n) / f64::from(u16::max_value())} - - (flt_color(cr.r()), flt_color(cr.g()), flt_color(cr.b())) -} - -impl draw::CacheImage for CrImage -{ - fn w(&self) -> draw::Coord - { - unsafe {gdk_pixbuf_get_width(self.0) as draw::Coord} - } - - fn h(&self) -> draw::Coord - { - unsafe {gdk_pixbuf_get_height(self.0) as draw::Coord} - } -} - -impl CrDrawArea -{ - /// Creates a new `CrDrawArea`. - pub fn new(ctx: *mut cairo_t, w: f64, h: f64) -> Self - { - let pan = unsafe { - let pan = pango_cairo_create_layout(ctx); - let dsc = pango_font_description_from_string(c_str!("Monospace 12")); - pango_layout_set_font_description(pan, dsc); - pango_font_description_free(dsc); - pan - }; - - let pan = Refc::new(pan); - - CrDrawArea{ctx, pan, w: w as draw::Coord, h: h as draw::Coord} - } -} - -impl draw::DrawArea for CrDrawArea -{ - type NativeImage = CrImage; - - fn w(&self) -> draw::Coord {self.w} - fn h(&self) -> draw::Coord {self.h} - - fn clear(&mut self, cr: impl Color) - { - self.rect(draw::Rect{x: 0, y: 0, w: self.w(), h: self.h()}, cr); - - unsafe { - cairo_set_line_width(self.ctx, 1.0); - } - } - - fn line_width(&mut self, width: u8) - { - let width = f64::from(width); - - unsafe { - cairo_set_line_width(self.ctx, width); - } - } - - fn line(&mut self, p1: draw::Point, p2: draw::Point, cr: impl Color) - { - let (r, g, b) = flt_color(cr); - - let x1 = f64::from(p1.0); - let y1 = f64::from(p1.1); - - let x2 = f64::from(p2.0); - let y2 = f64::from(p2.1); - - unsafe { - cairo_set_source_rgb(self.ctx, r, g, b); - cairo_move_to(self.ctx, x1, y1); - cairo_line_to(self.ctx, x2, y2); - cairo_stroke(self.ctx); - } - } - - fn rect(&mut self, rect: draw::Rect, cr: impl Color) - { - let px = f64::from(rect.x); - let py = f64::from(rect.y); - let sx = f64::from(rect.w); - let sy = f64::from(rect.h); - - let (r, g, b) = flt_color(cr); - - unsafe { - cairo_set_source_rgb(self.ctx, r, g, b); - cairo_rectangle(self.ctx, px, py, sx, sy); - cairo_fill(self.ctx); - } - } - - fn text(&mut self, pos: draw::Point, text: &str, cr: impl Color) - { - let (r, g, b) = flt_color(cr); - - let x = f64::from(pos.0); - let y = f64::from(pos.1); - - let tlen = text.len() as ffi::c_int; - let text = text.as_ptr() as ffi::NT; - - unsafe { - cairo_set_source_rgb(self.ctx, r, g, b); - cairo_move_to(self.ctx, x, y); - - pango_layout_set_markup(*self.pan, text, tlen); - pango_cairo_update_layout(self.ctx, *self.pan); - pango_cairo_show_layout(self.ctx, *self.pan); - } - } - - fn image(&mut self, pos: draw::Point, im: &Self::NativeImage) - { - let x = f64::from(pos.0); - let y = f64::from(pos.1); - - unsafe { - gdk_cairo_set_source_pixbuf(self.ctx, im.0, x, y); - cairo_paint(self.ctx); - } - } -} - -/// An image for a `CrDrawArea`. -pub struct CrImage(pub *const GdkPixbuf); - -/// A `DrawArea` for a Cairo surface. -pub struct CrDrawArea -{ - ctx: *mut cairo_t, - pan: Refc<'static, PangoLayout>, - w: draw::Coord, - h: draw::Coord, -} - -// EOF diff --git a/source/tycho/interfaces/editor.rs b/source/tycho/interfaces/editor.rs deleted file mode 100644 index 5dc22c5..0000000 --- a/source/tycho/interfaces/editor.rs +++ /dev/null @@ -1,49 +0,0 @@ -//! Map editor interface. - -use super::glib::*; -use gobject_sys::*; -use gtk_sys::*; -use maraiah::{durandal::ffi, marathon::map}; -use std::cell::RefCell; - -impl EditorModel -{ - pub fn new(view: EditorView) -> Self - { - Self{view} - } - - pub fn open_new(&mut self) - { - eprintln!("open_new"); - } - - pub fn open_buf(&mut self, b: &[u8]) - { - eprintln!("open_buf"); - } -} - -pub struct EditorPresenter -{ -} - -pub struct EditorView -{ - pub prop: PropertiesWindow, -} - -pub struct PropertiesWindow -{ - pub flg_ent: Vec>, - pub flg_env: Vec>, - pub flg_msn: Vec>, -} - -pub struct EditorModel -{ -} - -pub type EditorRef = std::cell::RefCell; - -// EOF diff --git a/source/tycho/interfaces/glib.rs b/source/tycho/interfaces/glib.rs deleted file mode 100644 index 087673e..0000000 --- a/source/tycho/interfaces/glib.rs +++ /dev/null @@ -1,113 +0,0 @@ -//! GLib interfaces. - -use glib_sys::*; -use gobject_sys::*; -use maraiah::durandal::ffi; -use std::marker::PhantomData; - -impl std::ops::Deref for Refc<'_, T> -{ - type Target = *mut T; - - fn deref(&self) -> &Self::Target {&self.p} -} - -impl Drop for Refc<'_, T> -{ - fn drop(&mut self) - { - unsafe { - g_object_unref(self.p as _); - } - } -} - -impl Refc<'_, T> -{ - /// Creates a new `Refc` which will own an already referenced object. - pub const fn new(p: *mut T) -> Self {Self{p, l: PhantomData}} - - /// Creates a new `Refc` which will hold a reference to the object. - pub fn own(p: *mut T) -> Self {unsafe {g_object_ref(p as _);} Self::new(p)} -} - -impl ListD -{ - pub fn new(head: *mut GList) -> Self {Self{head, iter: head}} -} - -impl Iterator for ListD -{ - type Item = gpointer; - - fn next(&mut self) -> Option { - if self.iter != ffi::null_mut() { - let obj = unsafe { - let obj = (*self.iter).data; - self.iter = (*self.iter).next; - obj - }; - - Some(obj) - } else { - None - } - } -} - -impl Drop for ListD -{ - fn drop(&mut self) {unsafe {g_list_free(self.head);}} -} - -impl ListS -{ - pub fn new(head: *mut GSList) -> Self {Self{head, iter: head}} -} - -impl Iterator for ListS -{ - type Item = gpointer; - - fn next(&mut self) -> Option { - if self.iter != ffi::null_mut() { - let obj = unsafe { - let obj = (*self.iter).data; - self.iter = (*self.iter).next; - obj - }; - - Some(obj) - } else { - None - } - } -} - -impl Drop for ListS -{ - fn drop(&mut self) {unsafe {g_slist_free(self.head);}} -} - -/// A GObject owned pointer. -pub struct Refc<'a, T> -{ - p: *mut T, - l: PhantomData<&'a *mut T>, -} - -/// A GList wrapper. -pub struct ListD -{ - head: *mut GList, - iter: *mut GList, -} - -/// A GSList wrapper. -pub struct ListS -{ - head: *mut GSList, - iter: *mut GSList, -} - -// EOF diff --git a/source/tycho/lib.rs b/source/tycho/lib.rs new file mode 100644 index 0000000..5d62dca --- /dev/null +++ b/source/tycho/lib.rs @@ -0,0 +1,7 @@ +#[no_mangle] +pub extern "C" fn test_fn() +{ + println!("hello, world! from rust"); +} + +// EOF diff --git a/source/tycho/main.rs b/source/tycho/main.rs deleted file mode 100644 index b06c140..0000000 --- a/source/tycho/main.rs +++ /dev/null @@ -1,374 +0,0 @@ -mod interfaces; - -use self::interfaces::*; -use gdk_pixbuf_sys::*; -use gdk_sys::*; -use gio_sys::*; -use glib_sys::*; -use gobject_sys::*; -use gtk_sys::*; -use maraiah::{c_str, - durandal::{err::*, ffi}}; -use std::{cell::RefCell, rc::Rc}; - -// Called when the application activates in order to set everything up. -unsafe extern "C" fn app_activate(app: *mut GtkApplication, _: gpointer) -{ - // Callback to finalize the reference. - unsafe extern "C" fn c_done(_: *mut GApplication, ptr: gpointer) - { - let edit = Rc::from_raw(ptr as *const EditorRef); - assert_eq!(Rc::strong_count(&edit), 1); - } - - let b = Refc::new(gtk_builder_new_from_resource(PATH_BUILDER)); - - let prop = PropertiesWindow{flg_ent: get_flag_fields(&b, B_CON_F_ENT), - flg_env: get_flag_fields(&b, B_CON_F_ENV), - flg_msn: get_flag_fields(&b, B_CON_F_MSN)}; - - let edit = EditorModel::new(EditorView{prop}); - let edit = RefCell::new(edit); - let edit = Rc::new(edit); - - setup_css(); - //setup_draw_area(&b, edit.clone()); - let wv = setup_win(&b, B_WIN_M_VIEW, B_BTN_M_VIEW); - let wt = setup_win(&b, B_WIN_M_TOOL, B_BTN_M_TOOL); - let _ = setup_win(&b, B_WIN_M_PROP, B_BTN_M_PROP); - gtk_widget_show_all(wv); - gtk_widget_show_all(wt); - - setup_about_dlg(&b); - setup_win_main(&b, app, edit.clone()); - - connect(app, E_SHUTDOWN, c_done as _, Rc::into_raw(edit)); -} - -// Gets all of the toggle buttons from a container. -unsafe fn get_flag_fields(b: &Refc, name: ffi::NT) - -> Vec> -{ - let mut flags = Vec::new(); - - let head = get_obj(b, name); - let head = ListD::new(gtk_container_get_children(head)); - let gtyp = gtk_toggle_button_get_type(); - - get_typed_from(head, gtyp, |obj| flags.push(Refc::own(obj as _))); - - flags -} - -// Sets up the map view window. -unsafe fn setup_win(b: &Refc, win: ffi::NT, btn: ffi::NT) - -> *mut GtkWidget -{ - // Callback to show the widget. - unsafe extern "C" fn c_show_act(_: *mut GtkWidget, wid: gpointer) - { - gtk_widget_show_all(wid as _); - } - - let win = get_obj::(b, win); - let btn = get_obj::(b, btn); - - connect_hide(win); - connect(btn, E_ACTIVATE, c_show_act as _, win); - - win as *mut GtkWidget -} - -// Sets up the about dialogue. -unsafe fn setup_about_dlg(b: &Refc) -{ - // Callback to show the dialogue when the "About" button is pressed, and - // hide it when the "Close" button is pressed on it. - unsafe extern "C" fn c_show_act(_: *mut GtkWidget, dlg: gpointer) - { - gtk_dialog_run(dlg as _); - gtk_widget_hide(dlg as _); - } - - let dlg = get_obj::(b, B_DLG_ABOUT); - let btn = get_obj::(b, B_BTN_ABOUT); - - let it = env!("CARGO_PKG_AUTHORS").split(';'); - let mut v = ffi::CStringVec::new_from_iter(it).unwrap(); - let img = Refc::new(load_img(IM_ABOUT)); - - gtk_about_dialog_set_authors(dlg, v.as_mut_ptr()); - gtk_about_dialog_set_version(dlg, c_str!(env!("CARGO_PKG_VERSION"))); - gtk_about_dialog_set_website(dlg, c_str!(env!("CARGO_PKG_HOMEPAGE"))); - gtk_about_dialog_set_logo(dlg, *img); - - connect_hide(dlg); - connect(btn, E_ACTIVATE, c_show_act as _, dlg); -} - -// Sets up explicit window finalization for the main window. -unsafe fn setup_explicit_drop(b: &Refc, win: *mut GtkWindow) -{ - // Callback to explicitly finalize all windows on exit. - unsafe extern "C" fn c_done(_: *mut GtkWidget, exp_del: gpointer) - { - let exp_del = Box::from_raw(exp_del as *mut Vec<*mut GtkWindow>); - - for win in *exp_del { - gtk_widget_destroy(win as _); - } - } - - // we need to explicitly drop other windows on exit, which means we need to - // create a list of them to send to the callback - let mut exp_del = Vec::new(); - - // so, we get all of the objects from the builder, and iterate through them - let head = ListS::new(gtk_builder_get_objects(**b)); - - get_typed_from(head, gtk_window_get_type(), |obj| { - let obj = obj as *mut GtkWindow; - - if obj != win { - exp_del.push(obj); - } - }); - - let exp_del = Box::into_raw(Box::new(exp_del)); - - connect(win, E_DESTROY, c_done as _, exp_del); -} - -// Get objects of type `ty` from `it`. -unsafe fn get_typed_from(it: I, ty: GType, mut f: F) - where I: Iterator, - F: FnMut(*mut GObject) -{ - for obj in it { - // while this is well-defined, it is a weird way of doing it, because - // this exact method of checking types isn't fully documented. we can't - // use the macros for this functionality because we're not using C, so we - // use the underlying function calls. again, get jacked, punk. - if g_type_check_instance_is_a(obj as *mut GTypeInstance, ty) != 0 { - f(obj as _); - } - } -} - -// Sets up the main menu window. -unsafe fn setup_win_main(b: &Refc, - app: *mut GtkApplication, - edit: Rc) -{ - // Callback to close the window when the "Quit" button is pressed. - unsafe extern "C" fn c_quit_act(_: *mut GtkWidget, win: gpointer) - { - gtk_window_close(win as _); - } - - // Callback to create a new map when the "New" button is pressed. - unsafe extern "C" fn c_new_act(_: *mut GtkWidget, edit: gpointer) - { - let edit = &*(edit as *const EditorRef); - - edit.borrow_mut().open_new(); - } - - // Opens the map editor with a buffer. - unsafe fn open_buf(path: &str, edit: &mut EditorModel) -> ResultS<()> - { - let fp = std::fs::File::open(&path)?; - let mm = memmap::Mmap::map(&fp)?; - - edit.open_buf(&mm); - - Ok(()) - } - - // Callback to open an existing map when the "Open" button is pressed. - unsafe extern "C" fn c_open_act(_: *mut GtkWidget, edit: gpointer) - { - let edit = &*(edit as *const EditorRef); - - if let Some(path) = run_file_chooser_open() { - // TODO: handle errors gracefully - open_buf(&path, &mut edit.borrow_mut()).unwrap(); - } - } - - // set up main window - let win = get_obj(b, B_WIN_MAIN); - - setup_explicit_drop(b, win); - - gtk_window_set_application(win, app); - gtk_widget_show_all(win as _); - - // set up buttons - let btn = get_obj::(b, B_BTN_QUIT); - connect(btn, E_ACTIVATE, c_quit_act as _, win); - - let btn = get_obj::(b, B_BTN_NEW); - connect(btn, E_ACTIVATE, c_new_act as _, connect_ref(btn, edit.clone())); - - let btn = get_obj::(b, B_BTN_OPEN); - connect(btn, E_ACTIVATE, c_open_act as _, connect_ref(btn, edit.clone())); -} - -// Sets up the CSS styling providers. -unsafe fn setup_css() -{ - let css = Refc::new(gtk_css_provider_new()); - gtk_css_provider_load_from_resource(*css, PATH_CSS); - - let scr = gdk_screen_get_default(); - let pri = GTK_STYLE_PROVIDER_PRIORITY_APPLICATION as u32; - gtk_style_context_add_provider_for_screen(scr, *css as _, pri); -} - -// Runs a modal Open File dialogue. -unsafe fn run_file_chooser_open() -> Option -{ - let action = GTK_FILE_CHOOSER_ACTION_OPEN; - let dlg = gtk_file_chooser_dialog_new(c_str!("Open File"), - ffi::null_mut(), - action, - c_str!("_Cancel"), - GTK_RESPONSE_CANCEL, - c_str!("_Open"), - GTK_RESPONSE_ACCEPT, - ffi::null_mut_void()); - - let res = gtk_dialog_run(dlg as _); - - let ret = if res == GTK_RESPONSE_ACCEPT { - let fna = gtk_file_chooser_get_filename(dlg as _); - - let own = ffi::CStr::from_ptr(fna); - let own = own.to_str().ok()?.to_owned(); - - g_free(fna as _); - - Some(own) - } else { - None - }; - - gtk_widget_destroy(dlg); - - ret -} - -// Connects a handler that hides a toplevel widget when deleted. -unsafe fn connect_hide(wid: *mut T) -{ - // Callback to hide the widget. - unsafe extern "C" fn c_hide_del(wid: *mut GtkWidget, - _: *mut GdkEvent, - _: gpointer) - { - gtk_widget_hide(wid); - } - - connect(wid, E_DELETE, c_hide_del as _, ffi::null_void()); -} - -// Connects the map editor reference to a widget. -unsafe fn connect_ref(obj: *mut T, rc: Rc) -> *const EditorRef -{ - // Callback to finalize the reference. - unsafe extern "C" fn c_done(_: *mut GtkWidget, ptr: gpointer) - { - Rc::from_raw(ptr as *const EditorRef); - } - - let ptr = Rc::into_raw(rc); - - connect(obj, E_DESTROY, c_done as _, ptr); - - ptr -} - -// Gets an object from a `GtkBuilder`. -unsafe fn get_obj(b: &Refc, name: ffi::NT) -> *mut T -{ - gtk_builder_get_object(**b, name) as _ -} - -// Connects a signal handler. -unsafe fn connect(obj: *mut T, name: ffi::NT, cb: gpointer, d: *const U) - -> ffi::c_ulong -{ - let cb = std::mem::transmute(cb); - g_signal_connect_data(obj as _, name, cb, d as _, None, 0) -} - -// Loads a `Pixbuf` from a resource. -unsafe fn load_img(path: ffi::NT) -> *mut GdkPixbuf -{ - gdk_pixbuf_new_from_resource(path, ffi::null_mut()) -} - -// Entry point. -fn main() -{ - unsafe { - // get jacked, punk. opaque data structures are for nerds. - const RESOURCE_DATA: &[u8] = - include_bytes!(concat!(env!("OUT_DIR"), "/resources")); - - // first we create the static resource header, which is really simple - let mut resource = GStaticResource{data: RESOURCE_DATA.as_ptr(), - data_len: RESOURCE_DATA.len(), - resource: ffi::null_mut(), - next: ffi::null_mut(), - padding: ffi::null_mut()}; - - // init it, now we can use it throughout the entire app without copying! - g_static_resource_init(&mut resource); - - { - // create and run the app - let app = Refc::new(gtk_application_new(APP_ID, 0)); - - connect(*app, E_ACTIVATE, app_activate as _, ffi::null_void()); - - g_application_run(*app as _, 0, ffi::null_mut()); - } - - // deinit the "static" data, and everything will be done - g_static_resource_fini(&mut resource); - } -} - -const APP_ID: ffi::NT = c_str!("net.greyserv.maraiah.tycho"); -const B_ADJ_M_HORZ: ffi::NT = c_str!("adj-map-horz"); -const B_ADJ_M_VERT: ffi::NT = c_str!("adj-map-vert"); -const B_BTN_ABOUT: ffi::NT = c_str!("btn-about"); -const B_BTN_M_PROP: ffi::NT = c_str!("btn-show-map-prop"); -const B_BTN_M_TOOL: ffi::NT = c_str!("btn-show-map-tools"); -const B_BTN_M_VIEW: ffi::NT = c_str!("btn-show-map-view"); -const B_BTN_NEW: ffi::NT = c_str!("btn-new"); -const B_BTN_OPEN: ffi::NT = c_str!("btn-open"); -const B_BTN_QUIT: ffi::NT = c_str!("btn-quit"); -const B_CON_F_ENT: ffi::NT = c_str!("con-f-ent"); -const B_CON_F_ENV: ffi::NT = c_str!("con-f-env"); -const B_CON_F_MSN: ffi::NT = c_str!("con-f-msn"); -const B_DLG_ABOUT: ffi::NT = c_str!("dlg-about"); -const B_DRAW_AREA: ffi::NT = c_str!("draw-area"); -const B_WIN_MAIN: ffi::NT = c_str!("win-main"); -const B_WIN_M_PROP: ffi::NT = c_str!("win-map-prop"); -const B_WIN_M_TOOL: ffi::NT = c_str!("win-map-tools"); -const B_WIN_M_VIEW: ffi::NT = c_str!("win-map-view"); -const E_ACTIVATE: ffi::NT = c_str!("activate"); -const E_DELETE: ffi::NT = c_str!("delete-event"); -const E_DESTROY: ffi::NT = c_str!("destroy"); -const E_DRAW: ffi::NT = c_str!("draw"); -const E_SHUTDOWN: ffi::NT = c_str!("shutdown"); -const E_TOGGLE: ffi::NT = c_str!("toggled"); -const IM_ABOUT: ffi::NT = c_str!("/net/greyserv/maraiah/tycho/tycho2.png"); -const IM_NOMAP: ffi::NT = c_str!("/net/greyserv/maraiah/tycho/tycho1.png"); -const PATH_BUILDER: ffi::NT = c_str!("/net/greyserv/maraiah/tycho/ui"); -const PATH_CSS: ffi::NT = c_str!("/net/greyserv/maraiah/tycho/css"); - -// EOF