Compare commits
15 commits
8f68ae45ce
...
c5c8b0f56d
Author | SHA1 | Date | |
---|---|---|---|
c5c8b0f56d | |||
88829b1660 | |||
e15db6f82f | |||
b4e3c1a425 | |||
9438d9d0b2 | |||
e5c67be41a | |||
c7e5a21be0 | |||
08738ed0cc | |||
2a2130f42f | |||
c794d7b8ca | |||
ef961265a5 | |||
e44f70bbac | |||
1c896b521d | |||
3116bceb66 | |||
8aba15baa2 |
16
assets/font/AUTHORS
Normal file
|
@ -0,0 +1,16 @@
|
|||
AUTHORS
|
||||
|
||||
Current Contributors (sorted alphabetically):
|
||||
|
||||
- Vishal Vijayraghavan <vishalvvr at fedoraproject dot org>
|
||||
Project Owner/ Maintainer (Current)
|
||||
Red Hat, Inc.
|
||||
|
||||
Previous Contributors
|
||||
- Pravin Satpute <psatpute at redhat dot com>
|
||||
Project Owner/ Maintainer
|
||||
Red Hat, Inc.
|
||||
|
||||
- Steve Matteson
|
||||
Original Designer
|
||||
Ascender, Inc.
|
102
assets/font/LICENSE
Normal file
|
@ -0,0 +1,102 @@
|
|||
Digitized data copyright (c) 2010 Google Corporation
|
||||
with Reserved Font Arimo, Tinos and Cousine.
|
||||
Copyright (c) 2012 Red Hat, Inc.
|
||||
with Reserved Font Name Liberation.
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License,
|
||||
Version 1.1.
|
||||
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
|
||||
PREAMBLE The goals of the Open Font License (OFL) are to stimulate
|
||||
worldwide development of collaborative font projects, to support the font
|
||||
creation efforts of academic and linguistic communities, and to provide
|
||||
a free and open framework in which fonts may be shared and improved in
|
||||
partnership with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves.
|
||||
The fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply to
|
||||
any document created using the fonts or their derivatives.
|
||||
|
||||
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such.
|
||||
This may include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components
|
||||
as distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting ? in part or in whole ?
|
||||
any of the components of the Original Version, by changing formats or
|
||||
by porting the Font Software to a new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical writer
|
||||
or other person who contributed to the Font Software.
|
||||
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,in
|
||||
Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the
|
||||
corresponding Copyright Holder. This restriction only applies to the
|
||||
primary font name as presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole, must
|
||||
be distributed entirely under this license, and must not be distributed
|
||||
under any other license. The requirement for fonts to remain under
|
||||
this license does not apply to any document created using the Font
|
||||
Software.
|
||||
|
||||
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are not met.
|
||||
|
||||
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER
|
||||
DEALINGS IN THE FONT SOFTWARE.
|
||||
|
BIN
assets/font/LiberationMono-Bold.ttf
Normal file
BIN
assets/font/LiberationMono-BoldItalic.ttf
Normal file
BIN
assets/font/LiberationMono-Italic.ttf
Normal file
BIN
assets/font/LiberationMono-Regular.ttf
Normal file
BIN
assets/font/LiberationSans-Bold.ttf
Normal file
BIN
assets/font/LiberationSans-BoldItalic.ttf
Normal file
BIN
assets/font/LiberationSans-Italic.ttf
Normal file
BIN
assets/font/LiberationSans-Regular.ttf
Normal file
BIN
assets/font/LiberationSerif-Bold.ttf
Normal file
BIN
assets/font/LiberationSerif-BoldItalic.ttf
Normal file
BIN
assets/font/LiberationSerif-Italic.ttf
Normal file
BIN
assets/font/LiberationSerif-Regular.ttf
Normal file
1
assets/icons/editor/actions/48/NOTE.txt
Normal file
|
@ -0,0 +1 @@
|
|||
Icons transform-move, transform-scale, and transform-rotate were modified from silk icons by maelstrom
|
BIN
assets/icons/editor/actions/48/edit-redo.png
Normal file
After Width: | Height: | Size: 625 B |
BIN
assets/icons/editor/actions/48/edit-undo.png
Normal file
After Width: | Height: | Size: 631 B |
BIN
assets/icons/editor/actions/48/object-group.png
Normal file
After Width: | Height: | Size: 553 B |
BIN
assets/icons/editor/actions/48/object-ungroup.png
Normal file
After Width: | Height: | Size: 666 B |
BIN
assets/icons/editor/actions/48/transform-move.png
Normal file
After Width: | Height: | Size: 355 B |
BIN
assets/icons/editor/actions/48/transform-rotate.png
Normal file
After Width: | Height: | Size: 443 B |
BIN
assets/icons/editor/actions/48/transform-scale.png
Normal file
After Width: | Height: | Size: 512 B |
22
assets/shaders/debug/debugfont.fs
Normal file
|
@ -0,0 +1,22 @@
|
|||
#version 330 core
|
||||
|
||||
out vec4 FragColor;
|
||||
in vec3 vPos;
|
||||
in vec2 vTexCoord;
|
||||
|
||||
uniform sampler2D fontTex;
|
||||
uniform int charIndex;
|
||||
|
||||
// Main
|
||||
|
||||
void main() {
|
||||
int x = (charIndex-32) % 16;
|
||||
int y = (charIndex-32) / 16;
|
||||
|
||||
float fx = float(x) / 16;
|
||||
float fy = float(y) / 8;
|
||||
|
||||
vec4 color = texture(fontTex, vec2(fx, fy) + vTexCoord * vec2(1.f/32, 1.f/16));
|
||||
FragColor = vec3(color) == vec3(0, 0, 0) ? vec4(0, 0, 0, 0) : color;
|
||||
// FragColor = color;
|
||||
}
|
12
assets/shaders/debug/debugfont.vs
Normal file
|
@ -0,0 +1,12 @@
|
|||
#version 330 core
|
||||
in vec3 aPos;
|
||||
in vec2 aTexCoord;
|
||||
|
||||
out vec3 vPos;
|
||||
out vec2 vTexCoord;
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(aPos, 1.0);
|
||||
vPos = aPos;
|
||||
vTexCoord = aTexCoord;
|
||||
}
|
|
@ -1,22 +1,14 @@
|
|||
// https://learnopengl.com/In-Practice/Text-Rendering
|
||||
|
||||
#version 330 core
|
||||
in vec2 TexCoords;
|
||||
out vec4 color;
|
||||
|
||||
out vec4 FragColor;
|
||||
in vec3 vPos;
|
||||
in vec2 vTexCoord;
|
||||
uniform sampler2D text;
|
||||
uniform vec3 textColor;
|
||||
|
||||
uniform sampler2D fontTex;
|
||||
uniform int charIndex;
|
||||
|
||||
// Main
|
||||
|
||||
void main() {
|
||||
int x = (charIndex-32) % 16;
|
||||
int y = (charIndex-32) / 16;
|
||||
|
||||
float fx = float(x) / 16;
|
||||
float fy = float(y) / 8;
|
||||
|
||||
vec4 color = texture(fontTex, vec2(fx, fy) + vTexCoord * vec2(1.f/32, 1.f/16));
|
||||
FragColor = vec3(color) == vec3(0, 0, 0) ? vec4(0, 0, 0, 0) : color;
|
||||
// FragColor = color;
|
||||
}
|
||||
void main()
|
||||
{
|
||||
vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, TexCoords).r);
|
||||
color = vec4(textColor, 1.0) * sampled;
|
||||
}
|
|
@ -1,12 +1,13 @@
|
|||
#version 330 core
|
||||
in vec3 aPos;
|
||||
in vec2 aTexCoord;
|
||||
// https://learnopengl.com/In-Practice/Text-Rendering
|
||||
|
||||
#version 330 core
|
||||
layout (location = 0) in vec4 vertex; // <vec2 pos, vec2 tex>
|
||||
out vec2 TexCoords;
|
||||
|
||||
uniform mat4 projection;
|
||||
|
||||
out vec3 vPos;
|
||||
out vec2 vTexCoord;
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(aPos, 1.0);
|
||||
vPos = aPos;
|
||||
vTexCoord = aTexCoord;
|
||||
}
|
||||
gl_Position = projection * vec4(vertex.xy, 0.0, 1.0);
|
||||
TexCoords = vertex.zw;
|
||||
}
|
|
@ -34,7 +34,7 @@ int main() {
|
|||
glewInit();
|
||||
|
||||
gDataModel->Init();
|
||||
renderInit(window, 1200, 900);
|
||||
renderInit(1200, 900);
|
||||
|
||||
// Baseplate
|
||||
gWorkspace()->AddChild(Part::New({
|
||||
|
@ -66,7 +66,7 @@ int main() {
|
|||
|
||||
processInput(window);
|
||||
gWorkspace()->PhysicsStep(deltaTime);
|
||||
render(window);
|
||||
render();
|
||||
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
|
|
|
@ -7,6 +7,7 @@ find_package(OpenGL)
|
|||
find_package(glm CONFIG REQUIRED)
|
||||
find_package(ReactPhysics3D REQUIRED)
|
||||
find_package(pugixml 1.15 REQUIRED)
|
||||
find_package(Freetype)
|
||||
|
||||
find_package(Stb REQUIRED)
|
||||
include_directories(${Stb_INCLUDE_DIR})
|
||||
|
@ -44,7 +45,7 @@ list(APPEND SOURCES ${AUTOGEN_OUTS})
|
|||
add_library(openblocks STATIC ${SOURCES})
|
||||
set_target_properties(openblocks PROPERTIES OUTPUT_NAME "openblocks")
|
||||
target_link_directories(openblocks PUBLIC ${LUAJIT_LIBRARY_DIRS})
|
||||
target_link_libraries(openblocks ${GLEW_LIBRARIES} ${LUAJIT_LIBRARIES} OpenGL::GL ReactPhysics3D::ReactPhysics3D pugixml::pugixml)
|
||||
target_link_libraries(openblocks ${GLEW_LIBRARIES} ${LUAJIT_LIBRARIES} OpenGL::GL ReactPhysics3D::ReactPhysics3D pugixml::pugixml Freetype::Freetype)
|
||||
target_include_directories(openblocks PUBLIC "src" "../include" ${LUAJIT_INCLUDE_DIRS})
|
||||
add_dependencies(openblocks autogen_build autogen)
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <vector>
|
||||
#include "datatypes/annotation.h"
|
||||
#include "error/data.h"
|
||||
#include "lua.h" // IWYU pragma: keep
|
||||
#include "luaapis.h" // IWYU pragma: keep
|
||||
|
||||
struct _EnumData {
|
||||
std::string name;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include "error/data.h"
|
||||
#include "variant.h"
|
||||
#include <pugixml.hpp>
|
||||
#include "lua.h" // IWYU pragma: keep
|
||||
#include "luaapis.h" // IWYU pragma: keep
|
||||
#include <sstream>
|
||||
|
||||
// null
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <memory>
|
||||
#include <optional>
|
||||
#include "objects/base/instance.h"
|
||||
#include "lua.h" // IWYU pragma: keep
|
||||
#include "luaapis.h" // IWYU pragma: keep
|
||||
#include "objects/base/member.h"
|
||||
#include <pugixml.hpp>
|
||||
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
#include "signal.h"
|
||||
#include "datatypes/base.h"
|
||||
#include "variant.h"
|
||||
#include "lua.h" // IWYU pragma: keep
|
||||
#include "luaapis.h" // IWYU pragma: keep
|
||||
#include <cstdio>
|
||||
#include <pugixml.hpp>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
extern const char* WRAPPER_SRC; // TODO: Move this to a shared header
|
||||
int script_errhandler(lua_State*); // extern
|
||||
|
||||
SignalSource::SignalSource() : std::shared_ptr<Signal>(std::make_shared<Signal>()) {}
|
||||
SignalSource::~SignalSource() = default;
|
||||
|
||||
|
@ -25,6 +28,8 @@ LuaSignalConnection::LuaSignalConnection(lua_State* L, std::weak_ptr<Signal> par
|
|||
// Save function and current thread so they don't get GC'd
|
||||
function = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
lua_pushthread(L);
|
||||
// For posterity, since I accidentally removed this once, the parent thread must not be
|
||||
// deleted because it may (likely) contain upvalues that the handler references
|
||||
thread = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
}
|
||||
|
||||
|
@ -56,18 +61,21 @@ static void stackdump(lua_State* L) {
|
|||
void LuaSignalConnection::Call(std::vector<Variant> args) {
|
||||
lua_State* thread = lua_newthread(state);
|
||||
|
||||
// Push function
|
||||
// Push wrapepr as thread function
|
||||
luaL_loadbuffer(thread, WRAPPER_SRC, strlen(WRAPPER_SRC), "=PCALL_WRAPPER");
|
||||
|
||||
// Push function as upvalue for wrapper
|
||||
lua_rawgeti(thread, LUA_REGISTRYINDEX, function);
|
||||
|
||||
// Also push our error handler and generate wrapped function
|
||||
lua_pushcfunction(thread, script_errhandler);
|
||||
lua_call(thread, 2, 1);
|
||||
|
||||
for (Variant arg : args) {
|
||||
arg.PushLuaValue(thread);
|
||||
}
|
||||
|
||||
int status = lua_resume(thread, args.size());
|
||||
if (status > LUA_YIELD) {
|
||||
Logger::error(lua_tostring(thread, -1));
|
||||
lua_pop(thread, 1); // Pop return value
|
||||
}
|
||||
lua_resume(thread, args.size());
|
||||
|
||||
lua_pop(state, 1); // Pop thread
|
||||
}
|
||||
|
@ -152,11 +160,7 @@ void Signal::Fire(std::vector<Variant> args) {
|
|||
arg.PushLuaValue(thread);
|
||||
}
|
||||
|
||||
int status = lua_resume(thread, args.size());
|
||||
if (status > LUA_YIELD) {
|
||||
Logger::error(lua_tostring(thread, -1));
|
||||
lua_pop(thread, 1); // Pop return value
|
||||
}
|
||||
lua_resume(thread, args.size());
|
||||
|
||||
// Remove thread from registry
|
||||
luaL_unref(thread, LUA_REGISTRYINDEX, threadId);
|
||||
|
|
77
core/src/lua/instancelib.cpp
Normal file
|
@ -0,0 +1,77 @@
|
|||
#include "objects/base/instance.h"
|
||||
#include "datatypes/ref.h"
|
||||
#include "luaapis.h" // IWYU pragma: keep
|
||||
#include "objects/meta.h"
|
||||
#include <memory>
|
||||
|
||||
static int lib_Instance_index(lua_State*);
|
||||
static int lib_Instance_tostring(lua_State*);
|
||||
static const struct luaL_Reg lib_Instance_metatable [] = {
|
||||
{"__index", lib_Instance_index},
|
||||
{"__tostring", lib_Instance_tostring},
|
||||
{NULL, NULL} /* end of array */
|
||||
};
|
||||
|
||||
static int __lua_impl__Instance__new(lua_State* L) {
|
||||
int n = lua_gettop(L);
|
||||
|
||||
// First argument (className)
|
||||
std::string className = luaL_checkstring(L, 1);
|
||||
|
||||
// [Optional] Second argument (parent)
|
||||
std::shared_ptr<Instance> parent;
|
||||
if (n > 1) {
|
||||
parent = **(std::shared_ptr<Instance>**)luaL_checkudata(L, 2, "__mt_instance");
|
||||
}
|
||||
|
||||
// Look up class name
|
||||
if (INSTANCE_MAP.count(className) == 0)
|
||||
return luaL_error(L, "Attempt to create instance of unknown type '%s'", className.c_str());
|
||||
|
||||
const InstanceType* type = INSTANCE_MAP[className];
|
||||
|
||||
if (type->flags & (INSTANCE_NOTCREATABLE | INSTANCE_SERVICE) || type->constructor == nullptr)
|
||||
return luaL_error(L, "Attempt to create Instance of type '%s', which is not creatable", className.c_str());
|
||||
|
||||
std::shared_ptr<Instance> object = type->constructor();
|
||||
|
||||
if (parent != nullptr)
|
||||
object->SetParent(parent);
|
||||
|
||||
InstanceRef(object).PushLuaValue(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Instance::PushLuaLibrary(lua_State* L) {
|
||||
lua_getglobal(L, "_G");
|
||||
lua_pushstring(L, "Instance");
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
|
||||
// Create the library's metatable
|
||||
luaL_newmetatable(L, "__mt_lib_Instance");
|
||||
luaL_register(L, NULL, lib_Instance_metatable);
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
lua_rawset(L, -3);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
|
||||
int lib_Instance_tostring(lua_State* L) {
|
||||
lua_pushstring(L, "Instance");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_Instance_index(lua_State* L) {
|
||||
std::string key(lua_tostring(L, 2));
|
||||
lua_pop(L, 2);
|
||||
|
||||
if (key == "new") {
|
||||
lua_pushcfunction(L, __lua_impl__Instance__new);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return luaL_error(L, "%s is not a valid member of %s\n", key.c_str(), "Instance");
|
||||
}
|
||||
|
|
@ -95,6 +95,7 @@ public:
|
|||
|
||||
// Instance is abstract, so it should not implement GetClass directly
|
||||
virtual const InstanceType* GetClass() = 0;
|
||||
static void PushLuaLibrary(lua_State*); // Defined in lua/instancelib.cpp
|
||||
bool SetParent(std::optional<std::shared_ptr<Instance>> newParent);
|
||||
std::optional<std::shared_ptr<Instance>> GetParent();
|
||||
bool IsParentLocked();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "script.h"
|
||||
#include "common.h"
|
||||
#include "lauxlib.h"
|
||||
#include "logger.h"
|
||||
#include "objects/base/instance.h"
|
||||
#include "objects/base/member.h"
|
||||
|
@ -7,12 +8,16 @@
|
|||
#include "objects/service/workspace.h"
|
||||
#include "objects/datamodel.h"
|
||||
#include "datatypes/ref.h"
|
||||
#include "lua.h" // IWYU pragma: keep
|
||||
#include "luaapis.h" // IWYU pragma: keep
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
int script_wait(lua_State*);
|
||||
int script_delay(lua_State*);
|
||||
int script_errhandler(lua_State*);
|
||||
|
||||
// TODO: Move this to a shared header
|
||||
const char* WRAPPER_SRC = "local func, errhandler = ... return function(...) local args = {...} xpcall(function() func(unpack(args)) end, errhandler) end";
|
||||
|
||||
Script::Script(): Instance(&TYPE) {
|
||||
source = "print(\"Hello, world!\")";
|
||||
|
@ -25,6 +30,7 @@ void Script::Run() {
|
|||
std::shared_ptr<ScriptContext> scriptContext = dataModel().value()->GetService<ScriptContext>();
|
||||
|
||||
lua_State* L = scriptContext->state;
|
||||
int top = lua_gettop(L);
|
||||
|
||||
// Create thread
|
||||
this->thread = lua_newthread(L);
|
||||
|
@ -52,43 +58,28 @@ void Script::Run() {
|
|||
|
||||
lua_pop(Lt, 1); // _G
|
||||
|
||||
// Load source and push onto thread stack as function ptr
|
||||
// luaL_loadstring(Lt, source.c_str());
|
||||
luaL_loadbuffer(Lt, source.c_str(), source.size(), scriptContext->RegisterScriptSource(shared<Script>()).c_str());
|
||||
|
||||
int status = lua_resume(Lt, 0);
|
||||
if (status > LUA_YIELD) {
|
||||
lua_Debug dbg;
|
||||
lua_getstack(Lt, 1, &dbg);
|
||||
lua_getinfo(Lt, "S", &dbg);
|
||||
// Push wrapper as thread function
|
||||
luaL_loadbuffer(Lt, WRAPPER_SRC, strlen(WRAPPER_SRC), "=PCALL_WRAPPER");
|
||||
|
||||
std::weak_ptr<Script> source = scriptContext->GetScriptFromSource(dbg.source);
|
||||
// Load source code and push onto thread as upvalue for wrapper
|
||||
int status = luaL_loadbuffer(Lt, source.c_str(), source.size(), this->GetFullName().c_str());
|
||||
if (status != LUA_OK) {
|
||||
// Failed to parse/load chunk
|
||||
Logger::error(lua_tostring(Lt, -1));
|
||||
|
||||
std::string errorMessage = lua_tostring(Lt, -1);
|
||||
if (!source.expired())
|
||||
errorMessage = source.lock()->GetFullName() + errorMessage.substr(errorMessage.find(':'));
|
||||
|
||||
Logger::error(errorMessage);
|
||||
lua_pop(Lt, 1); // Pop return value
|
||||
|
||||
Logger::traceStart();
|
||||
|
||||
int stack = 1;
|
||||
while (lua_getstack(Lt, stack++, &dbg)) {
|
||||
lua_getinfo(Lt, "nlSu", &dbg);
|
||||
|
||||
std::weak_ptr<Script> source = scriptContext->GetScriptFromSource(dbg.source);
|
||||
if (source.expired()) {
|
||||
Logger::trace(dbg.source, dbg.currentline);
|
||||
} else {
|
||||
Logger::trace(source.lock()->GetFullName(), dbg.currentline, &source);
|
||||
}
|
||||
}
|
||||
|
||||
Logger::traceEnd();
|
||||
lua_settop(L, top);
|
||||
return;
|
||||
}
|
||||
|
||||
// Push our error handler and then generate the wrapped function
|
||||
lua_pushcfunction(Lt, script_errhandler);
|
||||
lua_call(Lt, 2, 1);
|
||||
|
||||
// Resume the thread
|
||||
lua_resume(Lt, 0);
|
||||
|
||||
lua_pop(L, 1); // Pop the thread
|
||||
lua_settop(L, top);
|
||||
}
|
||||
|
||||
void Script::Stop() {
|
||||
|
@ -121,5 +112,29 @@ int script_delay(lua_State* L) {
|
|||
// Schedule next run
|
||||
scriptContext->PushThreadSleep(Lt, secs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int script_errhandler(lua_State* L) {
|
||||
std::string errorMessage = lua_tostring(L, -1);
|
||||
Logger::error(errorMessage);
|
||||
|
||||
// Traceback
|
||||
|
||||
Logger::traceStart();
|
||||
|
||||
lua_Debug dbg;
|
||||
int stack = 1;
|
||||
while (lua_getstack(L, stack++, &dbg)) {
|
||||
lua_getinfo(L, "nlSu", &dbg);
|
||||
// Ignore C frames and internal wrappers
|
||||
if (strcmp(dbg.what, "C") == 0 || strcmp(dbg.source, "=PCALL_WRAPPER") == 0)
|
||||
continue;
|
||||
|
||||
Logger::trace(dbg.source, dbg.currentline);
|
||||
}
|
||||
|
||||
Logger::traceEnd();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
#include "timeutil.h"
|
||||
#include <ctime>
|
||||
#include <string>
|
||||
#include "lua.h" // IWYU pragma: keep
|
||||
#include "luaapis.h" // IWYU pragma: keep
|
||||
|
||||
static int g_print(lua_State*);
|
||||
static int g_require(lua_State*);
|
||||
|
@ -46,6 +46,7 @@ void ScriptContext::InitService() {
|
|||
Vector3::PushLuaLibrary(state);
|
||||
CFrame::PushLuaLibrary(state);
|
||||
Color3::PushLuaLibrary(state);
|
||||
Instance::PushLuaLibrary(state);
|
||||
|
||||
// TODO: custom os library
|
||||
|
||||
|
@ -105,11 +106,7 @@ void ScriptContext::RunSleepingThreads() {
|
|||
// Time args
|
||||
lua_pushnumber(sleep.thread, float(tu_clock_micros() - sleep.timeYieldedWhen) / 1'000'000);
|
||||
lua_pushnumber(sleep.thread, float(tu_clock_micros()) / 1'000'000);
|
||||
int status = lua_resume(sleep.thread, 2);
|
||||
if (status > LUA_YIELD) {
|
||||
Logger::error(lua_tostring(sleep.thread, -1));
|
||||
lua_pop(sleep.thread, 1); // Pop return value
|
||||
}
|
||||
lua_resume(sleep.thread, 2);
|
||||
|
||||
// Remove thread
|
||||
deleted = true;
|
||||
|
@ -134,23 +131,6 @@ void ScriptContext::RunSleepingThreads() {
|
|||
schedTime = tu_clock_micros() - startTime;
|
||||
}
|
||||
|
||||
std::string ScriptContext::RegisterScriptSource(std::shared_ptr<Script> script) {
|
||||
// If it has already been registered, reference it here
|
||||
for (auto& [id, script2] : scriptSources) {
|
||||
if (!script2.expired() && script2.lock() == script)
|
||||
return "=f" + std::to_string(id);
|
||||
}
|
||||
|
||||
int id = lastScriptSourceId++;
|
||||
scriptSources[id] = script;
|
||||
return "=f" + std::to_string(id);
|
||||
}
|
||||
|
||||
std::weak_ptr<Script> ScriptContext::GetScriptFromSource(std::string source) {
|
||||
int id = std::stoi(source.c_str() + 2);
|
||||
return scriptSources[id];
|
||||
}
|
||||
|
||||
// https://www.lua.org/source/5.1/lbaselib.c.html
|
||||
static int g_print(lua_State* L) {
|
||||
std::string buf;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include "objects/annotation.h"
|
||||
#include "objects/base/service.h"
|
||||
#include "lua.h" // IWYU pragma: keep
|
||||
#include "luaapis.h" // IWYU pragma: keep
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
|
@ -19,7 +19,6 @@ class DEF_INST_SERVICE ScriptContext : public Service {
|
|||
AUTOGEN_PREAMBLE
|
||||
|
||||
std::vector<SleepingThread> sleepingThreads;
|
||||
std::map<int, std::weak_ptr<Script>> scriptSources;
|
||||
int lastScriptSourceId = 0;
|
||||
protected:
|
||||
void InitService() override;
|
||||
|
@ -32,8 +31,6 @@ public:
|
|||
lua_State* state;
|
||||
void PushThreadSleep(lua_State* thread, float delay);
|
||||
void RunSleepingThreads();
|
||||
std::string RegisterScriptSource(std::shared_ptr<Script>);
|
||||
std::weak_ptr<Script> GetScriptFromSource(std::string source);
|
||||
|
||||
static inline std::shared_ptr<Instance> Create() { return std::make_shared<ScriptContext>(); };
|
||||
};
|
|
@ -7,19 +7,19 @@
|
|||
#include <string>
|
||||
|
||||
extern int viewportWidth, viewportHeight;
|
||||
extern Texture* fontTexture;
|
||||
extern Shader* fontShader;
|
||||
extern Texture* debugFontTexture;
|
||||
extern Shader* debugFontShader;
|
||||
extern Shader* identityShader;
|
||||
|
||||
void drawChar(char c, int x, int y, float scale=1.f) {
|
||||
fontShader->use();
|
||||
fontTexture->activate(1);
|
||||
fontShader->set("fontTex", 1);
|
||||
debugFontShader->use();
|
||||
debugFontTexture->activate(1);
|
||||
debugFontShader->set("fontTex", 1);
|
||||
|
||||
fontShader->set("charIndex", (int)c);
|
||||
debugFontShader->set("charIndex", (int)c);
|
||||
|
||||
// https://stackoverflow.com/a/10631263
|
||||
int tex = fontShader->getAttribute("aTexCoord");
|
||||
int tex = debugFontShader->getAttribute("aTexCoord");
|
||||
|
||||
y = viewportHeight - y - 16*scale;
|
||||
float x0 = float(x)/viewportWidth, y0 = float(y)/viewportHeight, x1 = ((float)x + 8*scale)/viewportWidth, y1 = ((float)y + 16*scale)/viewportHeight;
|
||||
|
|
162
core/src/rendering/font.cpp
Normal file
|
@ -0,0 +1,162 @@
|
|||
#include "font.h"
|
||||
#include "logger.h"
|
||||
#include "panic.h"
|
||||
#include "rendering/shader.h"
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GL/gl.h>
|
||||
#include <glm/ext/matrix_clip_space.hpp>
|
||||
#include <memory>
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
// https://learnopengl.com/In-Practice/Text-Rendering
|
||||
|
||||
FT_Library freetype;
|
||||
Shader* fontShader;
|
||||
|
||||
extern int viewportWidth, viewportHeight;
|
||||
|
||||
unsigned int textVAO, textVBO;
|
||||
|
||||
void fontInit() {
|
||||
if (FT_Error err = FT_Init_FreeType(&freetype)) {
|
||||
Logger::fatalErrorf("Failed to initialize Freetype: [%d]", err);
|
||||
panic();
|
||||
}
|
||||
|
||||
fontShader = new Shader("assets/shaders/font.vs", "assets/shaders/font.fs");
|
||||
|
||||
// Set up buffer
|
||||
glGenVertexArrays(1, &textVAO);
|
||||
glBindVertexArray(textVAO);
|
||||
|
||||
glGenBuffers(1, &textVBO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, textVBO);
|
||||
|
||||
// Dynamic, because we update the vertices often V~~~~~~~~~~~~~~
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void fontFinish() {
|
||||
if (FT_Error err = FT_Done_FreeType(freetype)) {
|
||||
Logger::fatalErrorf("Failed to free Freetype: [%d]", err);
|
||||
panic();
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Font> loadFont(std::string fontName) {
|
||||
std::string fontPath = "assets/font/" + fontName;
|
||||
|
||||
FT_Face face;
|
||||
if (FT_Error err = FT_New_Face(freetype, fontPath.c_str(), 0, &face)) {
|
||||
Logger::fatalErrorf("Failed to create font '%s': [%d]", fontName.c_str(), err);
|
||||
panic();
|
||||
}
|
||||
|
||||
std::shared_ptr<Font> font = std::make_shared<Font>();
|
||||
|
||||
FT_Set_Pixel_Sizes(face, 0, 48);
|
||||
|
||||
// Load each glyph
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
for (unsigned char c = 0; c < 128; c++) {
|
||||
// load character glyph
|
||||
if (FT_Error err = FT_Load_Char(face, c, FT_LOAD_RENDER)) {
|
||||
Logger::errorf("Failed to load glyph %d in font '%s': [%d]", c, fontName.c_str(), err);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Generate texture
|
||||
unsigned int texture;
|
||||
glGenTextures(1, &texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_RED,
|
||||
face->glyph->bitmap.width,
|
||||
face->glyph->bitmap.rows,
|
||||
0,
|
||||
GL_RED,
|
||||
GL_UNSIGNED_BYTE,
|
||||
face->glyph->bitmap.buffer
|
||||
);
|
||||
// set texture options
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
// now store character for later use
|
||||
Character character;
|
||||
character.ID = texture;
|
||||
character.size = glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows);
|
||||
character.bearing = glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top);
|
||||
character.advance = (unsigned int)face->glyph->advance.x;
|
||||
font->characters[c] = character;
|
||||
}
|
||||
|
||||
FT_Done_Face(face);
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
void drawText(std::shared_ptr<Font> font, std::string text, float x, float y, float scale, glm::vec3 color) {
|
||||
// activate corresponding render state
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
fontShader->use();
|
||||
fontShader->set("textColor", color);
|
||||
fontShader->set("text", 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glm::mat4 projection = glm::ortho(0.0f, (float)viewportWidth, 0.0f, (float)viewportHeight);
|
||||
fontShader->set("projection", projection);
|
||||
|
||||
// This is not in the learnopengl guide but it is VERY important
|
||||
// I'm surprised I missed it but honestly... not so much. I'm an idiot
|
||||
glBindVertexArray(textVAO);
|
||||
|
||||
// iterate through all characters
|
||||
for (size_t i = 0; i < text.size(); i++) {
|
||||
unsigned char c = text[i];
|
||||
Character ch = font->characters[c];
|
||||
|
||||
float xpos = x + ch.bearing.x * scale;
|
||||
float ypos = y - (ch.size.y - ch.bearing.y) * scale;
|
||||
|
||||
float w = ch.size.x * scale;
|
||||
float h = ch.size.y * scale;
|
||||
// render glyph texture over quad
|
||||
glBindTexture(GL_TEXTURE_2D, ch.ID);
|
||||
|
||||
float vertices[6][4] = {
|
||||
{ xpos, ypos + h, 0.0f, 0.0f },
|
||||
{ xpos, ypos, 0.0f, 1.0f },
|
||||
{ xpos + w, ypos, 1.0f, 1.0f },
|
||||
|
||||
{ xpos, ypos + h, 0.0f, 0.0f },
|
||||
{ xpos + w, ypos, 1.0f, 1.0f },
|
||||
{ xpos + w, ypos + h, 1.0f, 0.0f }
|
||||
};
|
||||
// render glyph texture over quad
|
||||
glBindTexture(GL_TEXTURE_2D, ch.ID);
|
||||
// update content of VBO memory
|
||||
glBindBuffer(GL_ARRAY_BUFFER, textVBO);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
// render quad
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
// now advance cursors for next glyph (note that advance is number of 1/64 pixels)
|
||||
x += (ch.advance >> 6) * scale; // bitshift by 6 to get value in pixels (2^6 = 64)
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
23
core/src/rendering/font.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
// https://learnopengl.com/In-Practice/Text-Rendering
|
||||
|
||||
struct Character {
|
||||
unsigned int ID; // ID handle of the glyph texture
|
||||
glm::ivec2 size; // Size of glyph
|
||||
glm::ivec2 bearing; // Offset from baseline to left/top of glyph
|
||||
unsigned int advance; // Offset to advance to next glyph
|
||||
};
|
||||
|
||||
struct Font {
|
||||
Character characters[128];
|
||||
};
|
||||
|
||||
void fontInit();
|
||||
void fontFinish();
|
||||
std::shared_ptr<Font> loadFont(std::string fontName);
|
||||
void drawText(std::shared_ptr<Font> font, std::string text, float x, float y, float scale=1.f, glm::vec3 color = glm::vec3(1,1,1));
|
|
@ -1,5 +1,4 @@
|
|||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <GL/gl.h>
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
|
@ -23,6 +22,7 @@
|
|||
#include "math_helper.h"
|
||||
#include "objects/service/selection.h"
|
||||
#include "partassembly.h"
|
||||
#include "rendering/font.h"
|
||||
#include "rendering/mesh2d.h"
|
||||
#include "rendering/texture.h"
|
||||
#include "rendering/torus.h"
|
||||
|
@ -46,14 +46,16 @@ Shader* identityShader = NULL;
|
|||
Shader* ghostShader = NULL;
|
||||
Shader* wireframeShader = NULL;
|
||||
Shader* outlineShader = NULL;
|
||||
Shader* fontShader = NULL;
|
||||
Shader* debugFontShader = NULL;
|
||||
Shader* generic2dShader = NULL;
|
||||
extern Camera camera;
|
||||
Skybox* skyboxTexture = NULL;
|
||||
Texture3D* studsTexture = NULL;
|
||||
Texture* fontTexture = NULL;
|
||||
Texture* debugFontTexture = NULL;
|
||||
Mesh2D* rect2DMesh = NULL;
|
||||
|
||||
std::shared_ptr<Font> sansSerif;
|
||||
|
||||
bool debugRendererEnabled = false;
|
||||
bool wireframeRendering = false;
|
||||
|
||||
|
@ -62,7 +64,7 @@ int viewportWidth, viewportHeight;
|
|||
void renderDebugInfo();
|
||||
void drawRect(int x, int y, int width, int height, glm::vec3 color);
|
||||
|
||||
void renderInit(GLFWwindow* window, int width, int height) {
|
||||
void renderInit(int width, int height) {
|
||||
viewportWidth = width, viewportHeight = height;
|
||||
glViewport(0, 0, width, height);
|
||||
|
||||
|
@ -74,7 +76,7 @@ void renderInit(GLFWwindow* window, int width, int height) {
|
|||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
fontTexture = new Texture("assets/textures/debugfnt.bmp", GL_RGB);
|
||||
debugFontTexture = new Texture("assets/textures/debugfnt.bmp", GL_RGB);
|
||||
|
||||
skyboxTexture = new Skybox({
|
||||
"assets/textures/skybox/null_plainsky512_lf.jpg",
|
||||
|
@ -95,7 +97,7 @@ void renderInit(GLFWwindow* window, int width, int height) {
|
|||
ghostShader = new Shader("assets/shaders/ghost.vs", "assets/shaders/ghost.fs");
|
||||
wireframeShader = new Shader("assets/shaders/wireframe.vs", "assets/shaders/wireframe.fs");
|
||||
outlineShader = new Shader("assets/shaders/outline.vs", "assets/shaders/outline.fs");
|
||||
fontShader = new Shader("assets/shaders/font.vs", "assets/shaders/font.fs");
|
||||
debugFontShader = new Shader("assets/shaders/debug/debugfont.vs", "assets/shaders/debug/debugfont.fs");
|
||||
generic2dShader = new Shader("assets/shaders/generic2d.vs", "assets/shaders/generic2d.fs");
|
||||
|
||||
// Create mesh for 2d rectangle
|
||||
|
@ -110,6 +112,10 @@ void renderInit(GLFWwindow* window, int width, int height) {
|
|||
};
|
||||
|
||||
rect2DMesh = new Mesh2D(6, rectVerts);
|
||||
|
||||
// Initialize fonts
|
||||
fontInit();
|
||||
sansSerif = loadFont("LiberationSans-Regular.ttf");
|
||||
}
|
||||
|
||||
void renderParts() {
|
||||
|
@ -356,7 +362,6 @@ void renderHandles() {
|
|||
glm::vec4 screenPos = projection * view * glm::vec4((glm::vec3)cframe.Position(), 1.0f);
|
||||
screenPos /= screenPos.w;
|
||||
screenPos += 1; screenPos /= 2; screenPos.y = 1 - screenPos.y; screenPos *= glm::vec4(glm::vec2(viewportWidth, viewportHeight), 1, 1);
|
||||
printVec((glm::vec3)screenPos);
|
||||
|
||||
drawRect(screenPos.x - 3, screenPos.y - 3, 6, 6, glm::vec3(0, 1, 1));
|
||||
}
|
||||
|
@ -572,6 +577,7 @@ void renderRotationArcs() {
|
|||
handleShader->set("viewPos", camera.cameraPos);
|
||||
|
||||
PartAssembly assembly = PartAssembly::FromSelection(gDataModel->GetService<Selection>());
|
||||
if (assembly.size() == Vector3::ZERO) return; // No parts are selected
|
||||
|
||||
for (HandleFace face : HandleFace::Faces) {
|
||||
if (glm::any(glm::lessThan(face.normal, glm::vec3(0)))) continue;
|
||||
|
@ -644,7 +650,7 @@ void addDebugRenderCFrame(CFrame frame, Color3 color) {
|
|||
}
|
||||
|
||||
tu_time_t renderTime;
|
||||
void render(GLFWwindow* window) {
|
||||
void render() {
|
||||
tu_time_t startTime = tu_clock_micros();
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
@ -664,6 +670,7 @@ void render(GLFWwindow* window) {
|
|||
renderDebugInfo();
|
||||
// TODO: Make this a debug flag
|
||||
// renderAABB();
|
||||
|
||||
renderTime = tu_clock_micros() - startTime;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
#pragma once
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
extern bool wireframeRendering;
|
||||
|
||||
class CFrame;
|
||||
class Color3;
|
||||
|
||||
void renderInit(GLFWwindow* window, int width, int height);
|
||||
void render(GLFWwindow* window);
|
||||
void renderInit(int width, int height);
|
||||
void render();
|
||||
void setViewport(int width, int height);
|
||||
void addDebugRenderCFrame(CFrame);
|
||||
void addDebugRenderCFrame(CFrame, Color3);
|
||||
|
|
|
@ -7,7 +7,42 @@
|
|||
|
||||
struct vec { float x; float y; float z; };
|
||||
|
||||
void genTorusPoint(float outerRadius, float innerRadius, float tubeSides, float ringSides, int tube, int ring) {
|
||||
unsigned int torusVAO, torusVBO;
|
||||
int lastSize = 0;
|
||||
void initTorus(int tubeSides, int ringSides) {
|
||||
// Free existing buffer
|
||||
if (torusVAO != 0)
|
||||
glDeleteVertexArrays(1, &torusVAO);
|
||||
if (torusVBO != 0)
|
||||
glDeleteBuffers(1, &torusVBO);
|
||||
|
||||
lastSize = tubeSides * ringSides;
|
||||
|
||||
// Set up buffer
|
||||
glGenVertexArrays(1, &torusVAO);
|
||||
glBindVertexArray(torusVAO);
|
||||
|
||||
glGenBuffers(1, &torusVBO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, torusVBO);
|
||||
|
||||
// Dynamic, because we update the vertices often V~~~~~~~~~~~~~~
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8 * 6 * tubeSides * ringSides, NULL, GL_DYNAMIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(0 * sizeof(float)));
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
|
||||
glEnableVertexAttribArray(2);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void genTorusPoint(float* vertex, float outerRadius, float innerRadius, float tubeSides, float ringSides, int tube, int ring) {
|
||||
float angle = float(tube) / tubeSides * 2 * PI;
|
||||
float xL = innerRadius * cos(angle);
|
||||
float yL = innerRadius * sin(angle);
|
||||
|
@ -17,31 +52,41 @@ void genTorusPoint(float outerRadius, float innerRadius, float tubeSides, float
|
|||
float y = (outerRadius + xL) * sin(outerAngle);
|
||||
float z = yL;
|
||||
|
||||
// return vec { x, y, z };
|
||||
glVertex3f(x, y, z);
|
||||
vertex[0] = x; vertex[1] = y; vertex[2] = z;
|
||||
// TODO: Add normals and tex coords
|
||||
}
|
||||
|
||||
// made by yours truly
|
||||
void genTorus(float outerRadius, float innerRadius, int tubeSides, int ringSides) {
|
||||
glBegin(GL_TRIANGLES);
|
||||
// Automatically generate VBO ad-hoc
|
||||
if (lastSize != tubeSides * ringSides)
|
||||
initTorus(tubeSides, ringSides);
|
||||
|
||||
float* vertices = new float[(tubeSides * ringSides * 6) * 8];
|
||||
|
||||
int vi = 0;
|
||||
for (int i = 0; i < tubeSides; i++) {
|
||||
float tube = float(i) / tubeSides;
|
||||
for (int j = 0; j < ringSides; j++) {
|
||||
float ring = float(j) / ringSides;
|
||||
|
||||
int in = (i+1) % tubeSides;
|
||||
int jn = (j+1) % tubeSides;
|
||||
|
||||
genTorusPoint(outerRadius, innerRadius, tubeSides, ringSides, i, j);
|
||||
genTorusPoint(outerRadius, innerRadius, tubeSides, ringSides, in, j);
|
||||
genTorusPoint(outerRadius, innerRadius, tubeSides, ringSides, in, jn);
|
||||
genTorusPoint(&vertices[8*vi++], outerRadius, innerRadius, tubeSides, ringSides, i, j);
|
||||
genTorusPoint(&vertices[8*vi++], outerRadius, innerRadius, tubeSides, ringSides, in, j);
|
||||
genTorusPoint(&vertices[8*vi++], outerRadius, innerRadius, tubeSides, ringSides, in, jn);
|
||||
|
||||
genTorusPoint(outerRadius, innerRadius, tubeSides, ringSides, in, jn);
|
||||
genTorusPoint(outerRadius, innerRadius, tubeSides, ringSides, i, jn);
|
||||
genTorusPoint(outerRadius, innerRadius, tubeSides, ringSides, i, j);
|
||||
genTorusPoint(&vertices[8*vi++], outerRadius, innerRadius, tubeSides, ringSides, in, jn);
|
||||
genTorusPoint(&vertices[8*vi++], outerRadius, innerRadius, tubeSides, ringSides, i, jn);
|
||||
genTorusPoint(&vertices[8*vi++], outerRadius, innerRadius, tubeSides, ringSides, i, j);
|
||||
}
|
||||
}
|
||||
|
||||
glEnd();
|
||||
// Bind new data
|
||||
glBindBuffer(GL_ARRAY_BUFFER, torusVBO);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float) * 8 * 6 * tubeSides * ringSides, vertices);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
// Draw
|
||||
glBindVertexArray(torusVAO);
|
||||
glDrawArrays(GL_TRIANGLES, 0, tubeSides * ringSides * 6);
|
||||
}
|
3
deps.txt
|
@ -8,4 +8,5 @@ qt6
|
|||
reactphysics3d
|
||||
pugixml
|
||||
luajit
|
||||
qscintilla
|
||||
qscintilla
|
||||
freetype2
|
|
@ -98,14 +98,6 @@ add_custom_command(
|
|||
if (WIN32)
|
||||
#include("${QT_DEPLOY_SUPPORT}")
|
||||
|
||||
# TODO: Add other translations
|
||||
add_custom_command(
|
||||
TARGET editor POST_BUILD
|
||||
COMMAND ${WINDEPLOYQT_EXECUTABLE} $<TARGET_FILE:editor> --translations en --no-compiler-runtime --no-opengl-sw --no-system-d3d-compiler --plugindir $<TARGET_FILE_DIR:editor>/qtplugins
|
||||
)
|
||||
# No sense adding opengl-sw given that hardware acceleration is necessary, anyway
|
||||
# Also don't want to clutter with plugins, add only needed ones
|
||||
|
||||
# Copy over QScintilla DLLs
|
||||
# TODO: Use a better approach?
|
||||
add_custom_command(
|
||||
|
@ -113,6 +105,15 @@ if (WIN32)
|
|||
COMMAND ${CMAKE_COMMAND} -E copy ${QSCINTILLA_DLLS} $<TARGET_FILE_DIR:editor>
|
||||
)
|
||||
|
||||
# TODO: Add other translations
|
||||
add_custom_command(
|
||||
TARGET editor POST_BUILD
|
||||
COMMAND ${WINDEPLOYQT_EXECUTABLE} $<TARGET_FILE:editor> ${QSCINTILLA_DLLS} --dir $<TARGET_FILE_DIR:editor> --translations en --no-compiler-runtime --no-opengl-sw --no-system-d3d-compiler --plugindir $<TARGET_FILE_DIR:editor>/qtplugins
|
||||
)
|
||||
# No sense adding opengl-sw given that hardware acceleration is necessary, anyway
|
||||
# Also don't want to clutter with plugins, add only needed ones
|
||||
|
||||
|
||||
# Copy qt.conf to override default plugins location
|
||||
add_custom_command(
|
||||
TARGET editor POST_BUILD
|
||||
|
|
|
@ -1 +1,17 @@
|
|||
#pragma once
|
||||
#pragma once
|
||||
|
||||
inline bool isDarkMode() {
|
||||
// https://stackoverflow.com/a/78854851/16255372
|
||||
#if defined(_WIN32)
|
||||
// Never read dark theme on Windows as the app currently renders with white color palette regardless
|
||||
return false;
|
||||
#elif QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
|
||||
const auto scheme = QGuiApplication::styleHints()->colorScheme();
|
||||
return scheme == Qt::ColorScheme::Dark;
|
||||
#else
|
||||
const QPalette defaultPalette;
|
||||
const auto text = defaultPalette.color(QPalette::WindowText);
|
||||
const auto window = defaultPalette.color(QPalette::Window);
|
||||
return text.lightness() > window.lightness();
|
||||
#endif // QT_VERSION
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ MainGLWidget::MainGLWidget(QWidget* parent): QOpenGLWidget(parent), contextMenu(
|
|||
|
||||
void MainGLWidget::initializeGL() {
|
||||
glewInit();
|
||||
renderInit(NULL, width(), height());
|
||||
renderInit(width(), height());
|
||||
}
|
||||
|
||||
inline void playSound(QString path) {
|
||||
|
@ -63,7 +63,7 @@ extern std::weak_ptr<Part> draggingObject;
|
|||
extern std::optional<HandleFace> draggingHandle;
|
||||
extern Shader* shader;
|
||||
void MainGLWidget::paintGL() {
|
||||
::render(NULL);
|
||||
::render();
|
||||
}
|
||||
|
||||
bool isMouseRightDragging = false;
|
||||
|
|
|
@ -74,10 +74,16 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
ui->actionRedo->setShortcuts({QKeySequence("Ctrl+Shift+Z"), QKeySequence("Ctrl+Y")});
|
||||
|
||||
QIcon::setThemeSearchPaths(QIcon::themeSearchPaths() + QStringList { "./assets/icons" });
|
||||
|
||||
// Force theme under windows
|
||||
#ifdef _WIN32
|
||||
QIcon::setThemeName("editor");
|
||||
#else
|
||||
if (isDarkMode())
|
||||
QIcon::setFallbackThemeName("editor-dark");
|
||||
else
|
||||
QIcon::setThemeName("editor");
|
||||
QIcon::setFallbackThemeName("editor");
|
||||
#endif
|
||||
|
||||
// qApp->setStyle(QStyleFactory::create("fusion"));
|
||||
defaultMessageHandler = qInstallMessageHandler(logQtMessage);
|
||||
|
|
|
@ -306,8 +306,7 @@
|
|||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="edit-select">
|
||||
<normaloff>assets/icons/editor/drag.png</normaloff>assets/icons/editor/drag.png</iconset>
|
||||
<iconset theme="edit-select"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Select Objects</string>
|
||||
|
|
|
@ -14,27 +14,15 @@
|
|||
#include <qglobal.h>
|
||||
#include <qlayout.h>
|
||||
#include <qtextformat.h>
|
||||
#include "mainwindow.h"
|
||||
#include "objects/script.h"
|
||||
#include "datatypes/variant.h"
|
||||
#include <QPalette>
|
||||
#include <QStyleHints>
|
||||
#include "mainwindow.h"
|
||||
#include "editorcommon.h"
|
||||
#include "objects/script.h"
|
||||
#include "datatypes/variant.h"
|
||||
|
||||
QsciAPIs* makeApis(QsciLexer*);
|
||||
|
||||
inline bool isDarkMode() {
|
||||
// https://stackoverflow.com/a/78854851/16255372
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
|
||||
const auto scheme = QGuiApplication::styleHints()->colorScheme();
|
||||
return scheme == Qt::ColorScheme::Dark;
|
||||
#else
|
||||
const QPalette defaultPalette;
|
||||
const auto text = defaultPalette.color(QPalette::WindowText);
|
||||
const auto window = defaultPalette.color(QPalette::Window);
|
||||
return text.lightness() > window.lightness();
|
||||
#endif // QT_VERSION
|
||||
}
|
||||
|
||||
std::map<int, const QColor> DARK_MODE_COLOR_SCHEME = {{
|
||||
{QsciLexerLua::Comment, QColor("#808080")},
|
||||
{QsciLexerLua::LineComment, QColor("#808080")},
|
||||
|
@ -71,7 +59,7 @@ class ObLuaLexer : public QsciLexerLua {
|
|||
//"foreach foreachi getn "
|
||||
|
||||
// Openblocks extensions
|
||||
"shared require game workspace "
|
||||
"shared require game workspace Instance Instance.new "
|
||||
|
||||
"_G _VERSION getfenv getmetatable ipairs loadstring "
|
||||
"next pairs pcall rawequal rawget rawset select "
|
||||
|
@ -151,7 +139,8 @@ ScriptDocument::ScriptDocument(std::shared_ptr<Script> script, QWidget* parent):
|
|||
scintilla->setCaretForegroundColor(palette().text().color());
|
||||
scintilla->setFont(font);
|
||||
scintilla->setTabWidth(4);
|
||||
|
||||
scintilla->setEolMode(QsciScintilla::EolUnix); // LF endings
|
||||
|
||||
scintilla->setText(QString::fromStdString(script->source));
|
||||
|
||||
ObLuaLexer* lexer = new ObLuaLexer;
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
"stb",
|
||||
"reactphysics3d",
|
||||
"pkgconf",
|
||||
"luajit"
|
||||
"luajit",
|
||||
"freetype"
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
|
|