Browse Source

Add effect sample

Michael Ragazzon 2 years ago
parent
commit
78db66c15e

+ 7 - 0
CMake/SampleFileList.cmake

@@ -73,6 +73,13 @@ set(drag_SRC_FILES
     ${PROJECT_SOURCE_DIR}/Samples/basic/drag/src/main.cpp
     ${PROJECT_SOURCE_DIR}/Samples/basic/drag/src/main.cpp
 )
 )
 
 
+set(effect_HDR_FILES
+)
+
+set(effect_SRC_FILES
+    ${PROJECT_SOURCE_DIR}/Samples/basic/effect/src/main.cpp
+)
+
 set(loaddocument_HDR_FILES
 set(loaddocument_HDR_FILES
 )
 )
 
 

+ 1 - 1
CMake/gen_samplelists.sh

@@ -7,7 +7,7 @@ hdr='set(sample_HDR_FILES'
 srcdir='${PROJECT_SOURCE_DIR}'
 srcdir='${PROJECT_SOURCE_DIR}'
 srcpath=Samples
 srcpath=Samples
 samples=( 'shell'
 samples=( 'shell'
-	'basic/animation' 'basic/benchmark' 'basic/bitmapfont' 'basic/customlog' 'basic/databinding' 'basic/demo' 'basic/drag' 'basic/loaddocument' 'basic/treeview' 'basic/transform'
+	'basic/animation' 'basic/benchmark' 'basic/bitmapfont' 'basic/customlog' 'basic/databinding' 'basic/demo' 'basic/drag' 'basic/effect' 'basic/loaddocument' 'basic/treeview' 'basic/transform'
 	'basic/lottie' 'basic/svg'
 	'basic/lottie' 'basic/svg'
 	'tutorial/template' 'tutorial/drag'
 	'tutorial/template' 'tutorial/drag'
 	'invaders' 'luainvaders'
 	'invaders' 'luainvaders'

+ 4 - 1
CMakeLists.txt

@@ -814,7 +814,7 @@ endif()
 
 
 
 
 if(BUILD_SAMPLES)
 if(BUILD_SAMPLES)
-	set(samples treeview customlog drag loaddocument transform bitmapfont animation benchmark demo databinding)
+	set(samples treeview customlog drag loaddocument transform bitmapfont animation benchmark demo databinding effect)
 	set(tutorials template drag)
 	set(tutorials template drag)
 
 
 	if(ENABLE_LOTTIE_PLUGIN)
 	if(ENABLE_LOTTIE_PLUGIN)
@@ -963,6 +963,9 @@ if(BUILD_SAMPLES)
 	install(DIRECTORY ${PROJECT_SOURCE_DIR}/Samples/basic/demo/data
 	install(DIRECTORY ${PROJECT_SOURCE_DIR}/Samples/basic/demo/data
 			DESTINATION ${SAMPLES_DIR}/basic/demo
 			DESTINATION ${SAMPLES_DIR}/basic/demo
 	)
 	)
+	install(DIRECTORY ${PROJECT_SOURCE_DIR}/Samples/basic/effect/data
+			DESTINATION ${SAMPLES_DIR}/basic/effect
+	)
 	install(DIRECTORY ${PROJECT_SOURCE_DIR}/Samples/basic/transform/data
 	install(DIRECTORY ${PROJECT_SOURCE_DIR}/Samples/basic/transform/data
 			DESTINATION ${SAMPLES_DIR}/basic/transform
 			DESTINATION ${SAMPLES_DIR}/basic/transform
 	)
 	)

+ 112 - 0
Samples/basic/effect/data/effect.rml

@@ -0,0 +1,112 @@
+<rml>
+<head>
+<link type="text/rcss" href="/assets/rml.rcss"/>
+<link type="text/rcss" href="effect_style.rcss"/>
+<title>Effect Sample</title>
+<style>
+@spritesheet effect-sheet
+{
+	src: /assets/invader.tga;
+	icon-invader: 179px 152px 51px 39px;
+}
+
+.filter {
+	transform-origin: 50% 0;
+}
+
+.box {
+	color: black;
+	font-size: 18dp;
+	width: 280dp;
+	height: 70dp;
+	background: #fff8;
+	border: 2dp #def6f7;
+	margin: 10dp auto;
+	padding: 15dp;
+	border-radius: 30dp 8dp;
+	box-sizing: border-box;
+	position: relative;
+}
+.box img, .box .placeholder {
+	float: left;
+	margin-right: 8dp;
+}
+.box .placeholder {
+	width: 51dp;
+	height: 39dp;
+}
+.box .label {
+	color: #bbba;
+	position: absolute;
+	font-size: 0.75em;
+	bottom: 0.1em;
+	right: 1.5em;
+}
+
+.box.window {
+	position: absolute;
+	bottom: 50dp;
+	left: 50dp;
+	margin: 0;
+	cursor: move;
+}
+.box.window handle {
+	position: absolute;
+	top: 0; right: 0; bottom: 0; left: 0;
+	display: block;
+}
+.box.big {
+	width: 500dp;
+	height: 260dp;
+	max-width: 100%;
+	border-color: #333;
+}
+
+.transform, .filter.transform_all > .box { transform: rotate3d(0.2, 0.4, 0.1, 15deg); }
+
+</style>
+</head>
+<body
+	data-model="effects"
+	data-style-perspective="perspective >= 3000 ? 'none' : perspective + 'dp'"
+	data-style-perspective-origin-x="perspective_origin_x + '%'"
+	data-style-perspective-origin-y="perspective_origin_y + '%'"
+>
+<handle move_target="#document"><h1>Effect Sample</h1></handle>
+<handle class="size" size_target="#document"/>
+<div id="menu_button" data-class-open="show_menu" data-event-click="show_menu = !show_menu">—<br/>—<br/>—</div>
+<div id="menu" data-if="show_menu">
+	<div id="submenu">
+		<div data-event-click="submenu = 'filter'" data-class-selected="submenu == 'filter'">Filter</div>
+		<div data-event-click="submenu = 'transform'" data-class-selected="submenu == 'transform'">Transform</div>
+	</div>
+	<table>
+		<col style="width: 200%"/><col style="width: 300%"/><col style="width: 100%"/>
+		<tbody data-if="submenu == 'filter'">
+			<tr><td>Opacity</td><td><input type="range" min="0" max="1" step="0.01" data-value="opacity"/></td><td>{{ opacity }}</td></tr>
+		</tbody>
+		<tbody data-if="submenu == 'transform'">
+			<tr><td>Scale</td><td><input type="range" min="0.1" max="2.0" step="0.1" data-value="scale"/></td><td>{{ scale | format(1) }}x</td></tr>
+			<tr><td>Rotate X</td><td><input type="range" min="-90" max="90" step="5" data-value="rotate_x"/></td><td>{{ rotate_x }} deg</td></tr>
+			<tr><td>Rotate Y</td><td><input type="range" min="-90" max="90" step="5" data-value="rotate_y"/></td><td>{{ rotate_y }} deg</td></tr>
+			<tr><td>Rotate Z</td><td><input type="range" min="-90" max="90" step="5" data-value="rotate_z"/></td><td>{{ rotate_z }} deg</td></tr>
+			<tr><td>Perspective</td><td><input type="range" min="100" max="3000" step="25" data-value="perspective"/></td><td>{{ perspective >= 3000 ? 'none' : perspective + ' dp' }}</td></tr>
+			<tr><td>Perspective X</td><td><input type="range" min="-100" max="200" step="5" data-value="perspective_origin_x" data-attrif-disabled="perspective >= 3000"/></td><td>{{ perspective_origin_x }} %</td></tr>
+			<tr><td>Perspective Y</td><td><input type="range" min="-100" max="200" step="5" data-value="perspective_origin_y" data-attrif-disabled="perspective >= 3000"/></td><td>{{ perspective_origin_y }} %</td></tr>
+			<tr><td><label for="transform_all">Transform all</label></td><td colspan="2"><input id="transform_all" type="checkbox" data-checked="transform_all"/></td></tr>
+		</tbody>
+	</table>
+	<button data-event-click="reset()">Reset</button>
+</div>
+<div class="filter"
+	data-style-transform="'scale(' + scale + ') rotateX(' + rotate_x + 'deg) rotateY(' + rotate_y + 'deg) rotateZ(' + rotate_z + 'deg)'"
+	data-style-opacity="opacity"
+	data-class-transform_all="transform_all"
+>
+
+<div class="box"><img sprite="icon-invader"/>Hello, do you feel the funk?</div>
+<div class="box big"><img sprite="icon-invader"/>Hello, do you feel the funk?</div>
+
+</div>
+</body>
+</rml>

+ 196 - 0
Samples/basic/effect/data/effect_style.rcss

@@ -0,0 +1,196 @@
+body {
+	font-family: LatoLatin;
+	font-weight: normal;
+	font-style: normal;
+	font-size: 15dp;
+
+	left: 80dp;
+	right: 80dp;
+	top: 50dp;
+	bottom: 50dp;
+	min-width: 400dp;
+	min-height: 60dp;
+	background-color: #a4b6b7;
+	border: 3dp #d3e9ea;
+	border-radius: 30dp 8dp;
+	padding-top: 75dp;
+	overflow: hidden auto;
+}
+h1 {
+	margin: 0em 0 0.7em;
+	font-size: 22dp;
+	font-effect: glow(2dp #354c2e);
+	color: #fed;
+	padding: 1em 0 1em 40dp;
+	border-bottom: 3dp #d3e9ea;
+	background-color: #619158;
+	z-index: 1;
+	position: fixed;
+	top: 0;
+	right: 0;
+	left: 0;
+}
+handle.size {
+	position: fixed;
+	bottom: 0;
+	right: 0;
+	width: 18dp;
+	height: 18dp;
+	background-color: #d3e9ea66;
+	border-top-left-radius: 5dp;
+	cursor: resize;
+}
+handle.size:hover, handle.size:active {
+	background-color: #d3e9ea;
+}
+
+#menu_button {
+	position: fixed;
+	z-index: 2;
+	top: 15dp;
+	right: 25dp;
+	box-sizing: border-box;
+	width: 36dp;
+	height: 36dp;
+
+	background: #fffc;
+	border: 2dp #555a;
+	border-radius: 5dp;
+	color: #333;
+	padding-top: 5dp;
+	text-align: center;
+	line-height: 7dp;
+	font-size: 28dp;
+	cursor: pointer;
+}
+#menu_button.open {
+	background-color: #4bdc;
+	border-color: transparent;
+	border-top-right-radius: 15dp;
+}
+#menu_button:hover { background: #bcbc; }
+#menu_button:active { background: #abac; }
+#menu_button.open:hover { background: #5cec; }
+#menu_button.open:active { background: #4bdc; }
+
+#menu {
+	position: fixed;
+	z-index: 1;
+	top: 15dp;
+	right: 25dp;
+	box-sizing: border-box;
+	width: 400dp;
+	height: 415dp;
+	overflow: auto;
+
+	background: #fffc;
+	border: 2dp #555a;
+	border-radius: 15dp;
+	color: #222;
+	padding: 20dp 40dp 0dp;
+}
+#menu table {
+	margin-bottom: 10dp;
+}
+#menu td {
+	vertical-align: middle;
+	height: 36dp;
+	line-height: 16dp;
+}
+#menu td:nth-child(3) {
+	text-align: right;
+	white-space: nowrap;
+	font-size: 0.92em;
+}
+
+#submenu {
+	display: flex;
+	text-align: center;
+	margin-bottom: 20dp;
+	justify-content: space-around;
+}
+#submenu div {
+	flex: 0.35;
+	height: 25dp;
+	cursor: pointer;
+	border-bottom: 1dp #aaa;
+	box-sizing: border-box;
+}
+#submenu div:hover {
+	color: #000;
+	border-bottom-color: #555;
+}
+#submenu div.selected {
+	font-weight: bold;
+	color: #37a;
+	border-bottom-color: #4bd;
+	border-bottom: 2dp #37a;
+}
+
+scrollbarvertical {
+	margin-top: 75dp;
+	margin-bottom: 20dp;
+	margin-right: 0dp;
+	width: 0dp;
+}
+scrollbarvertical sliderbar {
+	margin-left: -14dp;
+	width: 12dp;
+	min-height: 25dp;
+	background: #d3e9ea66;
+	border-radius: 4dp;
+}
+scrollbarvertical sliderbar:hover, scrollbarvertical sliderbar:active {
+	background: #d3e9eaaa;
+}
+
+input.range {
+	width: 100%;
+	height: 15dp;
+	transition: opacity 0.2s cubic-out;
+}
+input.range:disabled { opacity: 0.3; }
+input.range slidertrack {
+	background-color: #fff;
+}
+input.range sliderbar {
+	width: 15dp;
+	border-radius: 3dp;
+}
+input.range:hover sliderbar { background-color: #333; }
+input.range sliderbar:active { background-color: #111; }
+input.range sliderbar, input.range sliderbar:disabled { background-color: #555; }
+input.range sliderarrowdec, input.range sliderarrowinc {
+	width: 12dp;
+	height: 15dp;
+}
+input.range sliderarrowdec { border-radius: 2dp 0 0 2dp; }
+input.range sliderarrowinc { border-radius: 0 2dp 2dp 0; }
+input.range sliderarrowdec:hover,    input.range sliderarrowinc:hover    { background-color: #ddd; }
+input.range sliderarrowdec:active,   input.range sliderarrowinc:active   { background-color: #eee; }
+input.range sliderarrowdec,          input.range sliderarrowinc,
+input.range sliderarrowdec:disabled, input.range sliderarrowinc:disabled { background-color: #ccc; }
+
+input.radio, input.checkbox {
+	width: 15dp;
+	height: 15dp;
+	border: 1dp #ccc;
+	background: #fff;
+	border-radius: 2dp;
+}
+input.radio {
+	border-radius: 8dp;
+}
+input.radio:hover,   input.checkbox:hover   { background-color: #ff3; }
+input.radio:active,  input.checkbox:active  { background-color: #ddd; }
+input.radio:checked, input.checkbox:checked { background-color: #555; }
+
+button {
+	border: 1dp #555;
+	border-radius: 7dp;
+	padding: 6dp 13dp;
+	background-color: #fffa;
+	cursor: pointer;
+}
+button:hover { background-color: #ccca; }
+button:active { background-color: #bbba; }

+ 140 - 0
Samples/basic/effect/src/main.cpp

@@ -0,0 +1,140 @@
+/*
+ * This source file is part of RmlUi, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://github.com/mikke89/RmlUi
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ * Copyright (c) 2019-2023 The RmlUi Team, and contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include <RmlUi/Core.h>
+#include <RmlUi/Debugger.h>
+#include <RmlUi_Backend.h>
+#include <Shell.h>
+
+#if defined RMLUI_PLATFORM_WIN32
+	#include <RmlUi_Include_Windows.h>
+int APIENTRY WinMain(HINSTANCE /*instance_handle*/, HINSTANCE /*previous_instance_handle*/, char* /*command_line*/, int /*command_show*/)
+#else
+int main(int /*argc*/, char** /*argv*/)
+#endif
+{
+	const int window_width = 1024;
+	const int window_height = 768;
+
+	// Initializes the shell which provides common functionality used by the included samples.
+	if (!Shell::Initialize())
+		return -1;
+
+	// Constructs the system and render interfaces, creates a window, and attaches the renderer.
+	if (!Backend::Initialize("Effect Sample", window_width, window_height, true))
+	{
+		Shell::Shutdown();
+		return -1;
+	}
+
+	// Install the custom interfaces constructed by the backend before initializing RmlUi.
+	Rml::SetSystemInterface(Backend::GetSystemInterface());
+	Rml::SetRenderInterface(Backend::GetRenderInterface());
+
+	// RmlUi initialisation.
+	Rml::Initialise();
+
+	// Create the main RmlUi context.
+	Rml::Context* context = Rml::CreateContext("main", Rml::Vector2i(window_width, window_height));
+	if (!context)
+	{
+		Rml::Shutdown();
+		Backend::Shutdown();
+		Shell::Shutdown();
+		return -1;
+	}
+
+	Rml::Debugger::Initialise(context);
+	Shell::LoadFonts();
+
+	static constexpr float perspective_max = 3000.f;
+
+	struct EffectData {
+		bool show_menu = false;
+		Rml::String submenu = "filter";
+
+		struct Filter {
+			float opacity = 1.0f;
+		} filter;
+
+		struct Transform {
+			float scale = 1.0f;
+			Rml::Vector3f rotate;
+			float perspective = perspective_max;
+			Rml::Vector2f perspective_origin = Rml::Vector2f(50.f);
+			bool transform_all = false;
+		} transform;
+	} data;
+
+	if (Rml::DataModelConstructor constructor = context->CreateDataModel("effects"))
+	{
+		constructor.Bind("show_menu", &data.show_menu);
+		constructor.Bind("submenu", &data.submenu);
+
+		constructor.Bind("opacity", &data.filter.opacity);
+
+		constructor.Bind("scale", &data.transform.scale);
+		constructor.Bind("rotate_x", &data.transform.rotate.x);
+		constructor.Bind("rotate_y", &data.transform.rotate.y);
+		constructor.Bind("rotate_z", &data.transform.rotate.z);
+		constructor.Bind("perspective", &data.transform.perspective);
+		constructor.Bind("perspective_origin_x", &data.transform.perspective_origin.x);
+		constructor.Bind("perspective_origin_y", &data.transform.perspective_origin.y);
+		constructor.Bind("transform_all", &data.transform.transform_all);
+
+		constructor.BindEventCallback("reset", [&data](Rml::DataModelHandle handle, Rml::Event& /*ev*/, const Rml::VariantList& /*arguments*/) {
+			if (data.submenu == "transform")
+				data.transform = EffectData::Transform{};
+			else if (data.submenu == "filter")
+				data.filter = EffectData::Filter{};
+			handle.DirtyAllVariables();
+		});
+	}
+
+	if (Rml::ElementDocument* document = context->LoadDocument("basic/effect/data/effect.rml"))
+		document->Show();
+
+	bool running = true;
+	while (running)
+	{
+		running = Backend::ProcessEvents(context, &Shell::ProcessKeyDownShortcuts, true);
+
+		context->Update();
+
+		Backend::BeginFrame();
+		context->Render();
+		Backend::PresentFrame();
+	}
+
+	Rml::Shutdown();
+
+	Backend::Shutdown();
+	Shell::Shutdown();
+
+	return 0;
+}