Added rss for blog.
8
.babelrc
Executable file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"plugins": [
|
||||
["@babel/plugin-transform-react-jsx", {
|
||||
"pragma": "h",
|
||||
"pragmaFrag": "Fragment",
|
||||
}]
|
||||
]
|
||||
}
|
||||
3
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
.hugo_build.lock
|
||||
/public/
|
||||
/resources/
|
||||
8
archetypes/default.md
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
title: "{{ replace .Name "-" " " | title }}"
|
||||
date: {{ .Date }}
|
||||
thumbnail: /img/fof.png
|
||||
draft: true
|
||||
tags: ["draft"]
|
||||
---
|
||||
|
||||
BIN
assets/thumbnails/c-socks.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
assets/thumbnails/ga.jpg
Normal file
|
After Width: | Height: | Size: 183 KiB |
BIN
assets/thumbnails/graphics.png
Normal file
|
After Width: | Height: | Size: 1 MiB |
BIN
assets/thumbnails/monq.jpg
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
assets/thumbnails/ramble.png
Normal file
|
After Width: | Height: | Size: 289 KiB |
BIN
assets/thumbnails/uni-graphics.png
Normal file
|
After Width: | Height: | Size: 1 MiB |
16
config.toml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
baseURL = "https://warwicknew.co.uk"
|
||||
languageCode = "en-us"
|
||||
title = "Warwick New"
|
||||
theme = "warwick_portfolio"
|
||||
pluralizeListTitles = false
|
||||
|
||||
[Author]
|
||||
name = "Warwick New"
|
||||
email = "wytau@sdf.org"
|
||||
|
||||
[outputs]
|
||||
home = ['html']
|
||||
section = ['html', 'rss']
|
||||
taxonomy = ['html']
|
||||
term = ['html']
|
||||
|
||||
65
content/blog/graphics-nothing-to-pbr.md
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
---
|
||||
title: "Graphics: Nothing to PBR"
|
||||
date: 2023-11-07T15:17:49Z
|
||||
thumbnail: /thumbnails/graphics.png
|
||||
tags: ["c/c++", "opengl", "glsl","cmake", "3d maths","games"]
|
||||
---
|
||||
I am someone who is fascinated by graphics programming, the creation of game engines and all things low-level. Here I've taken the time to create a proper graphics pipeline in order to create a PBR rendering system. I'll likely reuse the shaders and model loading classes in future projects but for my next personal graphics project I'm tempted to pick up some Vulkan and make greater use of namespaces and more modern general C++ programming paradigms to make something more robust to build on top of.
|
||||
|
||||
{{< video "/projects/videos/pbr-norm.mp4" >}}
|
||||
|
||||
## What steps did I take.
|
||||
I'm writing what I did up a little while after the fact, but he major steps I took were:
|
||||
- Setting up CMake/SDL/Opengl Boilerplate.
|
||||
- Implementing Camera Movement
|
||||
- Loading in models and textures
|
||||
- Implementing PBR (Physically Based Rendering)
|
||||
- Implementing Normal Maps.
|
||||
|
||||
Much of what I implemented here was made possible by [LearnOpenGL.com](https://learnopengl.com/) and [3Blue1Brown's series on Linear Algebra](https://www.3blue1brown.com/topics/linear-algebra), as well as my time as an undergrad at falmouth.
|
||||
|
||||
### Setting up SDL/Opengl Boilerplate.
|
||||
So back in the second year of my undergrad in computing for games I had worked with SDL and OpenGL to render some terrain in C++. The only problem being is that in my time since then I've come to hate my reliance on Visual Studio and undergrad levels of programming style at the time.
|
||||
|
||||
This pushed me to finally get some C++ build system knowledge and go through the initial stages of [LearnOpenGL](https://learnopengl.com/)'s tutorial using the libraries I preferred. At the time I wanted to keep to one library ecosystem and using SDL-image with SDL made more sense than using a separate header library stb_image with glfw3. Before long I had a simple textured square.
|
||||
|
||||

|
||||
|
||||
|
||||
## Implementing Camera Movement
|
||||
Following on from rendering a textured square I implemented an MVP stack. While I was at it I created objects to contain data to be rendered that also stored transforms. In this project practically all object transformations are stored as Matrices. I understand that in the long term this isn't ideal but it's good enough for a simple renderer.
|
||||
|
||||
{{< video "/posts/graphics-nothing-to-pbr/camera-movement.webm" >}}
|
||||
|
||||
## Loading in models and textures
|
||||
With the ability to look around objects I moved on to using [Assimp](https://www.assimp.org/) to load in models using [LearnOpenGL](https://learnopengl.com/)'s tutorial. Loading in Textures with the [SDL2-image](https://www.libsdl.org/projects/old/SDL_image/) library.
|
||||
|
||||
I ran into some weird issues along the way when it came to getting the image textures to work correctly, but I figured it out. I believe the textures initially weren't loaded into memory, then it was being loaded in upside down, before like Goldilocks, I got it just right.
|
||||
|
||||

|
||||
|
||||
I did go as far as implementing some simple diffuse lighting before deciding to just flat out and jump to PBR. And that gave some pretty good results. In hind sight I should have switch to working on other aspects of the project like giving it some a purpose other than rendering models. As this may have helped it keep my interest in the longer term.
|
||||
|
||||

|
||||
|
||||
## Implementing PBR (Physically Based Rendering)
|
||||
I then went through the steps to implement PBR from [LearnOpenGL](https://learnopengl.com/)'s articles. I didn't get at far as using textures for IBL or diffuse irradience, really I just wanted to focus on getting the lighting in. And I did it by implementing metalness, roughness, and AO in order. Other combinations of PBR layers exist but this was the one I chose.
|
||||
|
||||

|
||||
|
||||
I was also interested in texture packing so although it wasn't strictly necessary I got it rendering after packing each layer into the RGB values of a single texture (RMA aka. Roughness, Metallness, AO). This combined with some blender fu, allowed me to load in a single texture instead of three for PBR:
|
||||
|
||||

|
||||
|
||||
This gave me this result:
|
||||
|
||||
{{< video "/posts/graphics-nothing-to-pbr/pbr.mp4" >}}
|
||||
|
||||
## Implementing Normal Maps.
|
||||
The last step I took was to add normal maps as I felt that PBR alone was pretty flat. But I felt that so far I was following [LearnOpenGL](https://learnopengl.com/)'s articles too closely and not necessarily gaining a strong enough understanding of what was going on in the technique.
|
||||
|
||||
To counter this, I decided to calculate the tangent space of the normals at run time inside the GPU using the Geometry shader step, rather than caching tangents in another buffer like in [LearnOpenGL](https://learnopengl.com/)'s implementation. Doing while and referring to resources like [3Blue1Brown's series on Linear Algebra](https://www.3blue1brown.com/topics/linear-algebra), Gave me a much needed deeper under standing of linear algebra and how transforms actually work.
|
||||
|
||||
This gave me the last update of this project:
|
||||
|
||||
{{< video "/projects/videos/pbr-norm.mp4" >}}
|
||||
8
content/blog/playing-with-c-and-sockets.md
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
title: "Playing With C and Sockets"
|
||||
date: 2023-11-07T15:19:57Z
|
||||
thumbnail: /thumbnails/c-socks.png
|
||||
draft: true
|
||||
tags: ["c/c++", "web-development", "Sockets"]
|
||||
---
|
||||
|
||||
6
content/greeter.md
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: "Greeter"
|
||||
date: 2023-10-15T21:48:35+01:00
|
||||
---
|
||||
# Warwick
|
||||
Graphics, Games, Web, Education
|
||||
45
content/projects/monq.md
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
---
|
||||
title: "Monq"
|
||||
date: 2023-10-25T14:44:18+01:00
|
||||
thumbnail: /thumbnails/monq.jpg
|
||||
tags: ["unreal","c/c++","games"]
|
||||
---
|
||||
Monq is my most complete game project. I made it in my second year of
|
||||
university with some friends, and we were going to use it to form a successful
|
||||
startup. I learned a lot about how a multidisciplinary team works and tinkered
|
||||
with creating frameworks in C++ with inheritance both to blueprints and further
|
||||
C++ sub-classes, covering concepts such as all the AI using unreal's tools,
|
||||
puzzle implementation, shader implementation using noise and more. Most of the
|
||||
mechanics for which I was responsible, used a variety of vector and positional
|
||||
mathematics to implement.
|
||||
|
||||
## Trailer
|
||||
{{< youtube fRSD64D0LUw >}}
|
||||
|
||||
## Team
|
||||
**Programming:** Warwick New, James Hellman
|
||||
|
||||
**Designers:** James Hellman, Nicholas Stankowski
|
||||
|
||||
**Art:** Harri Slee, Robert Adolfson
|
||||
|
||||
**Music:** Jason Read
|
||||
|
||||
**Writing:** Michael Wheatley
|
||||
|
||||
**Animation:** George Evans, Ross Everson
|
||||
|
||||
## Main Contributions
|
||||
### Tiger AI
|
||||
Here I created an AI that guards an arena. The puzzle part of this boss was based on trying to get the ai to get a chain stuck on pillars left around the arena reducing the range it could navigate. I did this by calculating the distance between the previous attachment point and the next and reducing the available navigatable circumference of the tiger appropriately. Since this was my first more complicated AI, I now know that It would have been far easier to restrict the AI's movement through the use of a more complex steering system rather than calculating where the actor should target moving towards.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
### Mirror Reflections
|
||||
Here is an example of me simulating reflections in monq to create a light bounce puzzle. Each mirror triggers the next to recursively make light reflection beams. Here I had to work out angles of reflection before creating a new cast to attach a beam particle.
|
||||
|
||||
I also worked on the sand texture in this image mixing various forms of noise to create the ripples based on changes in topography.
|
||||
|
||||

|
||||
16
content/projects/ramble.md
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
title: "Ramble"
|
||||
date: 2023-11-07T14:46:17Z
|
||||
thumbnail: /thumbnails/ramble.png
|
||||
tags: ["javascript","react","nodejs","docker","dynamodb","janus","web-development"]
|
||||
---
|
||||
|
||||
Ramble was a web project I created during my master's degree to create a startup. In this project, I was the CTO and built a website that allowed users to stream their podcasts live and accept call-ins in a similar vein to talk shows! I learnt the entire JavaScript web development stack from React to audio streaming to DevOps in order to make it a reality.
|
||||
|
||||
It also had chatroom functionality with the ability to re-stream to audiences much like other apps that came out in the time since, such as Clubhouse.
|
||||
|
||||
During the project's lifespan of just under two years, I mostly worked on creating the streaming functionality of the project and managing how the project was designed to function behind the hood when it was deployed. I learned a ton about how web deployment works during this time allowing me to work on web development modules in the Games Academy at Falmouth University today.
|
||||
|
||||
Here's a demo of the project I took before we moved on.
|
||||
|
||||
{{< video "/projects/ramble/ramble.mp4" >}}
|
||||
18
content/projects/university-graphics-project.md
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
title: "University Graphics Project"
|
||||
date: 2023-10-25T11:56:20+01:00
|
||||
thumbnail: /thumbnails/uni-graphics.png
|
||||
tags: ["c/c++", "opengl", "glsl","cmake", "3d maths","games"]
|
||||
---
|
||||
|
||||
{{< video "/projects/videos/uni-graphics.mp4" >}}
|
||||
|
||||
I made this project for a module at uni. It's a terrain map based on perlin
|
||||
noise with flat face lighting, It was the first project where I picked up a lot
|
||||
of the 3D maths used in games and learned about simulation. It was my first
|
||||
project using GLSL with C++ and also the project I optimised for an
|
||||
optimisation module in my final year. Getting deep into learning more about
|
||||
memory management and Object-Oriented design.
|
||||
|
||||
#### Build
|
||||
- [Win64 Build](/builds/UniGraphics-Win64.zip)
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
title: "An Exploratory Analysis of Student Experiences With Peer Evaluation in Group Game Development Projects"
|
||||
date: 2023-11-07T15:23:05Z
|
||||
thumbnail: /thumbnails/ga.jpg
|
||||
tags: ["academia", "teaching", "student experience"]
|
||||
---
|
||||
Collaborative projects are commonplace in computing education. They typically enable students to gain experience building software in teams, equipping them with the teamwork skills they need to be competitive in the labour market. However, students often need encouragement to reflect upon and synthesise their experience to attain the most learning. Peer evaluation offers one such approach, but the conditions which facilitate effective peer evaluation have not yet been established. This paper seeks to provide insight into student experiences with peer evaluation. It builds upon prior qualitative work, analysing quantitative data collected through a questionnaire taken by undergraduate students on a collaborate digital game development module. An exploratory factor analysis identifies seven dimensions of variance in the student experience: perceived impact; arbitrary influence; inconsistency; team cohesiveness; assessment pressure; ease and professionalism. Correlation analysis suggests some factors such as arbitrary influence, team cohesion, assessment pressure, and professionalism are associated with attained learning, whilst factors such as inconsistency and onerousness are not. This informs the development of a conceptual framework, suggesting focuses which facilitate effective peer evaluation. Expanding this conceptual framework and validating it across different demographics, contexts, and project types are suggested as avenues for further investigation.
|
||||
|
||||
## Authors
|
||||
- [Alexander Mitchell](https://dl.acm.org/profile/99659739515)
|
||||
- [Michael Scott](https://dl.acm.org/profile/81555254356)
|
||||
- [Joseph Walton-Rivers](https://dl.acm.org/profile/99659883826)
|
||||
- [Matt Watkins](https://dl.acm.org/profile/81544299456)
|
||||
- [Warwick New](https://dl.acm.org/profile/99659883587)
|
||||
- [Douglas Brown](https://dl.acm.org/profile/99659333535)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
title: "Student Perspectives on the Purpose of Peer Evaluation During Group Game Development Projects"
|
||||
date: 2023-11-07T15:24:03Z
|
||||
thumbnail: /thumbnails/ga.jpg
|
||||
tags: ["academia", "teaching", "student experience"]
|
||||
---
|
||||
Being able to work well in a team is valued in industry and beyond. As such, many university educators strive to help their students to collaborate effectively. However, it is typically the case that more than ad-hoc experience is needed to master teamwork. Often, students need to become reflective practitioners who learn from their experiences and enact change. Self and peer evaluation can help evoke such reflection. However, the facilitating conditions for effective learning from peer evaluation during group projects in computing are not yet well-defined. This research is an initial step in identifying these conditions. In this study, students engaged in a long-term multidisciplinary software engineering project in which they produced a digital game. They completed regular exercises in which they reflected upon and wrote about their contributions to the project as well as those of their peers. Thematic analysis of 200 responses to an open-ended question about the purpose of these exercises illustrated student perspectives: giving and receiving feedback; prompting personal reflection and improvement; supporting supervision; aiding marking; informing project planning and management; exploring and reshaping group dynamics; improving project outputs; providing a system to hold group members accountable; and giving a sense of safety to raise issues without repercussion. Giving consideration to these differing perceptions will help educators to address student concerns about group projects, notably standardisation, workload efficiency, and fairness, and will lay the foundations for a model of peer evaluation which improves teamwork.
|
||||
|
||||
## Authors
|
||||
- [Alexander Mitchell](https://dl.acm.org/profile/99659739515)
|
||||
- [Terry Greer](https://dl.acm.org/profile/99659884092)
|
||||
- [Warwick New](https://dl.acm.org/profile/99659883587)
|
||||
- [Joseph Walton-Rivers](https://dl.acm.org/profile/99659883826)
|
||||
- [Matt Watkins](https://dl.acm.org/profile/81544299456)
|
||||
- [Douglas Brown](https://dl.acm.org/profile/99659333535)
|
||||
- [Michael Scott](https://dl.acm.org/profile/81555254356)
|
||||
BIN
static/builds/UniGraphics-Win64.zip
Normal file
BIN
static/favicon.ico
Normal file
|
After Width: | Height: | Size: 104 KiB |
BIN
static/posts/graphics-nothing-to-pbr/camera-movement.webm
Normal file
BIN
static/posts/graphics-nothing-to-pbr/diffuse-lighting.png
Normal file
|
After Width: | Height: | Size: 152 KiB |
BIN
static/posts/graphics-nothing-to-pbr/gl-boilerplate.png
Normal file
|
After Width: | Height: | Size: 119 KiB |
BIN
static/posts/graphics-nothing-to-pbr/loading-models.png
Normal file
|
After Width: | Height: | Size: 384 KiB |
BIN
static/posts/graphics-nothing-to-pbr/pbr.jpg
Normal file
|
After Width: | Height: | Size: 234 KiB |
BIN
static/posts/graphics-nothing-to-pbr/pbr.mp4
Normal file
BIN
static/posts/graphics-nothing-to-pbr/rma.jpg
Normal file
|
After Width: | Height: | Size: 2.3 MiB |
BIN
static/projects/monq/MirrorReflection.png
Normal file
|
After Width: | Height: | Size: 533 KiB |
BIN
static/projects/monq/TigerAI.png
Normal file
|
After Width: | Height: | Size: 839 KiB |
BIN
static/projects/monq/TigerDiagram.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
static/projects/ramble/ramble.mp4
Normal file
BIN
static/projects/videos/pbr-norm.mp4
Normal file
BIN
static/projects/videos/uni-graphics.mp4
Normal file
20
themes/warwick_portfolio/LICENSE
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 Warwick New
|
||||
|
||||
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.
|
||||
2
themes/warwick_portfolio/archetypes/default.md
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
+++
|
||||
+++
|
||||
116
themes/warwick_portfolio/assets/css/greeter.css
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
@keyframes slideInLeft {
|
||||
0% {
|
||||
transform: translateX(-100%);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
#greeter {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-content: space-around;
|
||||
flex-wrap: wrap;
|
||||
align-items: stretch;
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
animation: 1s ease-out 0s 1 slideInLeft;
|
||||
}
|
||||
|
||||
#greeter-sim {
|
||||
flex-grow: 2;
|
||||
}
|
||||
|
||||
#greeter-sim * {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#greeter-content {
|
||||
padding: 2%;
|
||||
margin: 0;
|
||||
flex-grow: 2;
|
||||
}
|
||||
|
||||
@media (max-width: 950px){
|
||||
#greeter-content {
|
||||
margin: 5% 5% 5% 5%;
|
||||
}
|
||||
}
|
||||
#greeter-content li {
|
||||
font-size: 133%;
|
||||
}
|
||||
|
||||
/* CSS scroll button */
|
||||
.scroll-down-dude {margin: 12px 0px 0px 24px;}
|
||||
.scroll-down-dude:before,
|
||||
.scroll-down-dude:after {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
transform: rotate(45deg);
|
||||
border-bottom: 4px solid white;
|
||||
border-right: 4px solid white;
|
||||
}
|
||||
|
||||
.scroll-down-dude:before {
|
||||
-webkit-animation: down-arrow-before 2.6s cubic-bezier(0.77, 0, 0.175, 1) infinite;
|
||||
animation: down-arrow-before 2.6s cubic-bezier(0.77, 0, 0.175, 1) infinite;
|
||||
}
|
||||
|
||||
.scroll-down-dude:after {
|
||||
-webkit-animation: down-arrow-after 2.6s cubic-bezier(0.77, 0, 0.175, 1) infinite;
|
||||
animation: down-arrow-after 2.6s cubic-bezier(0.77, 0, 0.175, 1) infinite;
|
||||
}
|
||||
|
||||
@-webkit-keyframes down-arrow-before {
|
||||
50% {
|
||||
transform: rotate(45deg) translate(70%, 70%);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(45deg) translate(70%, 70%);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes down-arrow-before {
|
||||
50% {
|
||||
transform: rotate(45deg) translate(70%, 70%);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(45deg) translate(70%, 70%);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes down-arrow-after {
|
||||
50% {
|
||||
transform: rotate(45deg) translate(110%, 110%);
|
||||
opacity: 0;
|
||||
}
|
||||
51% {
|
||||
transform: rotate(45deg) translate(-130%, -130%);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(45deg) translate(-70%, -70%);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes down-arrow-after {
|
||||
50% {
|
||||
transform: rotate(45deg) translate(110%, 110%);
|
||||
opacity: 0;
|
||||
}
|
||||
51% {
|
||||
transform: rotate(45deg) translate(-130%, -130%);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(45deg) translate(-70%, -70%);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
116
themes/warwick_portfolio/assets/css/main.css
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
/* Font stuff */
|
||||
@import url('https://fonts.googleapis.com/css?family=Abel:700|Abel:400');
|
||||
body {
|
||||
font-family: 'Abel';
|
||||
font-weight: 400;
|
||||
}
|
||||
h1, h2, h3, h4, h5 {
|
||||
font-family: 'Abel';
|
||||
font-weight: 700;
|
||||
}
|
||||
html {font-size: 100%;} /* 16px */
|
||||
h1 {font-size: 4.210rem; /* 67.36px */}
|
||||
h2 {font-size: 3.158rem; /* 50.56px */}
|
||||
h3 {font-size: 2.369rem; /* 37.92px */}
|
||||
h4 {font-size: 1.777rem; /* 28.48px */}
|
||||
h5 {font-size: 1.333rem; /* 21.28px */}
|
||||
small {font-size: 0.750rem; /* 12px */}
|
||||
|
||||
:root {
|
||||
--text: #b4bfc0;
|
||||
--background: #010202;
|
||||
--primary: #e3eff2;
|
||||
--secondary: #00bcd1;
|
||||
--accent: #8c240d;
|
||||
--paper: #050606;
|
||||
}
|
||||
|
||||
/* Custom CSS */
|
||||
body {
|
||||
color-scheme: dark;
|
||||
background-color: var(--background);
|
||||
accent-color: var(--accent);
|
||||
caret-color: var(--text);
|
||||
color: var(--text);
|
||||
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a:link, a:active{
|
||||
color: var(--primary);
|
||||
}
|
||||
a:visited {
|
||||
color: var(--accent);
|
||||
}
|
||||
a:hover {
|
||||
color: var(--secondary);
|
||||
}
|
||||
|
||||
.header {
|
||||
background-color: var(--paper);
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.homepage-header {
|
||||
background-color: var(--paper);
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
footer {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: .5rem;
|
||||
background: var(--paper);
|
||||
color: var(--text);
|
||||
font-weight: var(--text);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 0.2rem;
|
||||
}
|
||||
|
||||
.flex-wrap-container {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1000px;
|
||||
min-width: 800px;
|
||||
padding: 10px;
|
||||
background-color: var(--paper);
|
||||
margin: 10px auto;
|
||||
}
|
||||
|
||||
.flex-wrap-container .container {
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
.summary {
|
||||
z-index: 1;
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
#article-content img {
|
||||
max-width: 100%;
|
||||
max-height: 50vh;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
div.summary__img_container {
|
||||
position:relative; top:0; left:0; width:600px; height:250px;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
img.summary__img {
|
||||
position:absolute; top:0; right:0; width:600px; height:100%;
|
||||
-webkit-mask-image:-webkit-gradient(linear, right top, left top, from(rgba(0,0,0,1)), to(rgba(0,0,0,0)));
|
||||
mask-image: linear-gradient(to left, rgba(0,0,0,1), rgba(0,0,0,0));
|
||||
}
|
||||
BIN
themes/warwick_portfolio/assets/img/fof.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
themes/warwick_portfolio/assets/img/logo.png
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
themes/warwick_portfolio/assets/img/rss.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
100
themes/warwick_portfolio/assets/js/background.js
Executable file
|
|
@ -0,0 +1,100 @@
|
|||
// create background element
|
||||
let canvas = document.createElement("canvas");
|
||||
document.body.appendChild(canvas);
|
||||
canvas.style.cssText = `
|
||||
background: #00000000;
|
||||
position:fixed;
|
||||
left:0;
|
||||
top:0;
|
||||
z-index:-99999;
|
||||
`
|
||||
// set it's size
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
|
||||
let context = canvas.getContext('2d');
|
||||
|
||||
// this will be populated and used later
|
||||
drawableObjectList = [];
|
||||
|
||||
class Splash {
|
||||
constructor(distance, x, y) {
|
||||
this.distance = distance;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.time = 0;
|
||||
}
|
||||
draw() {
|
||||
context.fillStyle = "#00000000";
|
||||
context.strokeStyle = `rgba(140, 36, 13, ${this.distance + 0.1})`;
|
||||
|
||||
let splashSize = this.distance * (this.time/100);
|
||||
|
||||
context.beginPath();
|
||||
context.ellipse(this.x, this.y, 100 * splashSize , 50 * splashSize, 0, 0, Math.PI * 2);
|
||||
context.fill();
|
||||
context.stroke();
|
||||
|
||||
if (this.time > 100) {
|
||||
drawableObjectList = drawableObjectList.filter((item) => {return item !== this});
|
||||
}
|
||||
|
||||
this.time += 1;
|
||||
}
|
||||
}
|
||||
// this is the object that'll look cool
|
||||
class Drop {
|
||||
constructor() {
|
||||
this.x = Math.random() * window.innerWidth;
|
||||
this.y = Math.random() * window.innerHeight;
|
||||
|
||||
this.distance = Math.random();
|
||||
}
|
||||
draw() {
|
||||
context.fillStyle = `rgba(140, 36, 13, ${this.distance + 0.1})`;
|
||||
context.strokeStyle = `rgba(140, 36, 13, ${this.distance + 0.1})`;
|
||||
|
||||
// draw point
|
||||
context.beginPath();
|
||||
context.moveTo(this.x,this.y);
|
||||
context.lineTo(this.x,this.y-this.distance*100);
|
||||
context.stroke();
|
||||
// move point
|
||||
this.y += (this.distance + 0.3) * 4;
|
||||
|
||||
// keep point in bounds
|
||||
if (this.y > window.innerHeight - (1 - this.distance) * 300) {
|
||||
// Add splash
|
||||
drawableObjectList.push(new Splash(this.distance, this.x, this.y))
|
||||
|
||||
this.y = 0
|
||||
this.x = Math.random() * window.innerWidth;
|
||||
this.distance = Math.random();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// populate element array
|
||||
for (let i = 0; i < 50; i++) {
|
||||
drawableObjectList.push(new Drop());
|
||||
}
|
||||
|
||||
function loop() {
|
||||
// Loop and clear frame
|
||||
requestAnimationFrame(loop);
|
||||
context.clearRect(0, 0, window.innerWidth, window.innerHeight);
|
||||
|
||||
// Draw objects.
|
||||
drawableObjectList.forEach((point) => {
|
||||
point.draw();
|
||||
});
|
||||
|
||||
// Handle page size change
|
||||
if (canvas.width != window.innerWidth) {
|
||||
canvas.width = window.innerWidth;
|
||||
}
|
||||
if (canvas.height != window.innerHeight) {
|
||||
canvas.height = window.innerHeight;
|
||||
}
|
||||
}
|
||||
loop();
|
||||
117
themes/warwick_portfolio/assets/js/greeter.js
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
// thanks to https://stackoverflow.com/a/74129799
|
||||
const { cos, sin, sqrt, acos, atan, atan2, abs, PI } = Math
|
||||
const clamp = (a, b, x) => x < a ? a : x > b ? b : x
|
||||
const cvs = document.createElement('canvas')
|
||||
cvs.style.cssText = ` background: #00000000; `
|
||||
const primaryCol = getComputedStyle(document.body).getPropertyValue('--secondary');
|
||||
const secondCol = getComputedStyle(document.body).getPropertyValue('--accent');
|
||||
const ctx = cvs.getContext('2d')
|
||||
|
||||
const RADIUS = 150
|
||||
const NB_SECTIONS = 6
|
||||
const LINE_WIDTH = 3
|
||||
|
||||
const SCALE = devicePixelRatio
|
||||
const width = RADIUS * 2 + 20
|
||||
const height = RADIUS * 2 + 20
|
||||
cvs.width = width * SCALE
|
||||
cvs.height = height * SCALE
|
||||
cvs.style.width = `${width}px`
|
||||
cvs.style.height = `${height}px`
|
||||
|
||||
document.getElementById("greeter-sim").appendChild(cvs)
|
||||
|
||||
const vec = (x = 0, y = 0, z = 0) => ({ x, y, z })
|
||||
|
||||
vec.set = (o, x = 0, y = 0, z = 0) => {
|
||||
o.x = x
|
||||
o.y = y
|
||||
o.z = z
|
||||
return o
|
||||
}
|
||||
|
||||
const X = vec(1, 0, 0)
|
||||
const Y = vec(0, 1, 0)
|
||||
const Z = vec(0, 0, 1)
|
||||
|
||||
// orientation of camera
|
||||
let theta, phi
|
||||
|
||||
// project v to the camera, output to o
|
||||
function project(o, { x, y, z }) {
|
||||
let ct = cos(theta), st = sin(theta)
|
||||
let cp = cos(phi), sp = sin(phi)
|
||||
let a = x * ct + y * st
|
||||
return vec.set(o, y * ct - x * st, cp * z - sp * a, cp * a + sp * z)
|
||||
}
|
||||
|
||||
// draw camera-facing section of sphere with normal v and offset o (-1 < o < 1)
|
||||
const _p = vec()
|
||||
function draw_section(n, o = 0) {
|
||||
let { x, y, z } = project(_p, n) // project normal on camera
|
||||
let a = atan2(y, x) // angle of projected normal -> angle of ellipse
|
||||
let ry = sqrt(1 - o * o) // radius of section -> y-radius of ellipse
|
||||
let rx = ry * abs(z) // x-radius of ellipse
|
||||
let W = sqrt(x * x + y * y)
|
||||
let sa = acos(clamp(-1, 1, o * (1 / W - W) / rx)) // ellipse start angle
|
||||
let sb = z > 0 ? 2 * PI - sa : - sa // ellipse end angle
|
||||
|
||||
ctx.beginPath()
|
||||
ctx.ellipse(x * o * RADIUS, y * o * RADIUS, rx * RADIUS, ry * RADIUS, a, sa, sb, z <= 0)
|
||||
ctx.stroke()
|
||||
}
|
||||
|
||||
const _n = vec()
|
||||
function draw_arcs() {
|
||||
for (let i = NB_SECTIONS; i--;) {
|
||||
let a = i / NB_SECTIONS * Math.PI
|
||||
draw_section(vec.set(_n, cos(a), sin(a)))
|
||||
}
|
||||
|
||||
for (let i = NB_SECTIONS - 1; i--;) {
|
||||
let a = (i + 1) / NB_SECTIONS * Math.PI
|
||||
draw_section(Z, cos(a))
|
||||
//draw_section(X, cos(a))
|
||||
//draw_section(Y, cos(a))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ctx.lineCap = 'round'
|
||||
ctx.scale(SCALE, SCALE)
|
||||
|
||||
function render() {
|
||||
requestAnimationFrame(render)
|
||||
|
||||
theta = performance.now() / 24000 * PI
|
||||
phi = cos(performance.now() / 12000 * PI)
|
||||
|
||||
// 1. change the basis of the canvas
|
||||
ctx.save()
|
||||
ctx.clearRect(0, 0, width, height)
|
||||
ctx.translate(width >> 1, height >> 1)
|
||||
ctx.scale(1, -1)
|
||||
|
||||
// 2. draw back arcs
|
||||
ctx.lineWidth = LINE_WIDTH / 2
|
||||
ctx.strokeStyle = secondCol
|
||||
ctx.scale(-1, -1) // the trick is to flip the canvas
|
||||
draw_arcs()
|
||||
ctx.scale(-1, -1)
|
||||
|
||||
// 3. draw sphere border
|
||||
ctx.strokeStyle = primaryCol
|
||||
ctx.lineWidth = LINE_WIDTH + 2
|
||||
ctx.beginPath()
|
||||
ctx.arc(0, 0, RADIUS, 0, 2 * Math.PI)
|
||||
ctx.stroke()
|
||||
|
||||
// 4. draw front arcs
|
||||
ctx.lineWidth = LINE_WIDTH
|
||||
ctx.strokeStyle = primaryCol
|
||||
draw_arcs()
|
||||
|
||||
ctx.restore()
|
||||
}
|
||||
|
||||
requestAnimationFrame(render)
|
||||
0
themes/warwick_portfolio/layouts/404.html
Normal file
13
themes/warwick_portfolio/layouts/_default/baseof.html
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
{{- partial "head.html" . -}}
|
||||
<body>
|
||||
{{ if ne .IsHome true }}
|
||||
{{- partial "header.html" . -}}
|
||||
{{ end }}
|
||||
<div id="content">
|
||||
{{- block "main" . }}{{- end }}
|
||||
</div>
|
||||
{{- partial "footer.html" . -}}
|
||||
</body>
|
||||
</html>
|
||||
11
themes/warwick_portfolio/layouts/_default/list.html
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{{ define "main" -}}
|
||||
<div class="container">
|
||||
<h1> {{ .Title | title }} </h1>
|
||||
{{ .Content }}
|
||||
</div>
|
||||
{{range .Pages }}
|
||||
<div class="container">
|
||||
{{ .Render "summary" }}
|
||||
</div>
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
39
themes/warwick_portfolio/layouts/_default/rss.xml
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
{{- $pctx := . -}}
|
||||
{{- if .IsHome -}}{{ $pctx = .Site }}{{- end -}}
|
||||
{{- $pages := slice -}}
|
||||
{{- if or $.IsHome $.IsSection -}}
|
||||
{{- $pages = $pctx.RegularPages -}}
|
||||
{{- else -}}
|
||||
{{- $pages = $pctx.Pages -}}
|
||||
{{- end -}}
|
||||
{{- $limit := .Site.Config.Services.RSS.Limit -}}
|
||||
{{- if ge $limit 1 -}}
|
||||
{{- $pages = $pages | first $limit -}}
|
||||
{{- end -}}
|
||||
{{- printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" | safeHTML }}
|
||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<channel>
|
||||
<title>{{ if ne .Title .Site.Title }}{{ .Site.Title }}'s {{.Title}}{{ else }}{{ .Site.Title }}{{ end }}</title>
|
||||
<link>{{ .Permalink }}</link>
|
||||
<description>{{ if ne .Title .Site.Title }}{{ .Site.Title }}'s {{.Title}}{{ else }}{{ .Site.Title }}{{ end }}</description>
|
||||
<generator>Hugo -- gohugo.io</generator>{{ with .Site.LanguageCode }}
|
||||
<language>{{.}}</language>{{end}}{{ with .Site.Author.email }}
|
||||
<managingEditor>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</managingEditor>{{end}}{{ with .Site.Author.email }}
|
||||
<webMaster>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</webMaster>{{end}}{{ with .Site.Copyright }}
|
||||
<copyright>{{.}}</copyright>{{end}}{{ if not .Date.IsZero }}
|
||||
<lastBuildDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</lastBuildDate>{{ end }}
|
||||
{{ with .OutputFormats.Get "RSS" }}
|
||||
{{ printf "<atom:link href=%q rel=\"self\" type=%q />" .Permalink .MediaType | safeHTML }}
|
||||
{{ end }}
|
||||
{{ range $pages }}
|
||||
<item>
|
||||
<title>{{ .Title }}</title>
|
||||
<link>{{ .Permalink }}</link>
|
||||
<pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate>
|
||||
{{ with .Site.Author.email }}<author>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</author>{{end}}
|
||||
<guid>{{ .Permalink }}</guid>
|
||||
<description>{{ .Content | html }}</description>
|
||||
</item>
|
||||
{{ end }}
|
||||
</channel>
|
||||
</rss>
|
||||
15
themes/warwick_portfolio/layouts/_default/single.html
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{{define "main"}}
|
||||
<div class="container">
|
||||
<section id="single-article">
|
||||
<article id="article-content">
|
||||
<h1 style="margin-bottom: 1px"> {{.Title}} </h1>
|
||||
{{- partial "taglist.html" . -}}
|
||||
<time datetime="{{.Params.date.Format "2006-01-02T15:04:05"}}" class="index-article__date">
|
||||
{{.Params.date.Format "2 January 2006"}}
|
||||
</time>
|
||||
<hr>
|
||||
{{ .Content }}
|
||||
</article>
|
||||
</section>
|
||||
</div>
|
||||
{{end}}
|
||||
36
themes/warwick_portfolio/layouts/_default/summary.html
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
<div class="item">
|
||||
<div style="justify-content: space-between; flex-wrap:nowrap" class="flex-wrap-container">
|
||||
<div class="summary">
|
||||
<a class="summary__link" href="{{ .Permalink }}">
|
||||
{{ if gt (len .Title) 40}}
|
||||
<h4 style="margin: 0">{{slicestr .Title 0 40}}...</h4>
|
||||
{{ else }}
|
||||
<h4 style="margin: 0">{{ .Title }}</h4>
|
||||
{{ end }}
|
||||
{{- partial "taglist.html" . -}}
|
||||
</a>
|
||||
{{ if gt (len .Summary) 500 }}
|
||||
<p>{{slicestr .Summary 0 500}}...</p>
|
||||
{{ else }}
|
||||
<p>{{.Summary}}</p>
|
||||
{{ end }}
|
||||
<span class="summary__date">
|
||||
{{.Params.date.Format "2 January 2006"}}
|
||||
</span>
|
||||
</div>
|
||||
{{ if .Params.thumbnail }}
|
||||
{{- $image := resources.Get .Params.thumbnail -}}
|
||||
{{ if $image }}
|
||||
|
||||
<div class="summary__img_container" style="align-self: center">
|
||||
<a style="display: block" href="{{ .Permalink }}">
|
||||
<img
|
||||
class="summary__img"
|
||||
src="{{ ($image.Fill "600x200 q100 Center").RelPermalink }}"
|
||||
>
|
||||
</a>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
59
themes/warwick_portfolio/layouts/index.html
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
{{ define "main" }}
|
||||
{{ partial "greeter.html" .}}
|
||||
<header id="homepage-header" class="homepage-header">
|
||||
<div class="flex-wrap-container" style="align-items:center">
|
||||
{{ $logo := (resources.Get "/img/logo.png").Resize "100x100" }}
|
||||
<a href="/">
|
||||
<img style="padding-right: 1%" src="{{ $logo.RelPermalink }}" alt="logo">
|
||||
</a>
|
||||
<a style="text-decoration: none" href="/">
|
||||
<h1 style="display:inline; color:var(--primary)">{{.Title}}</h1>
|
||||
</a>
|
||||
<span style="margin-left: auto;">
|
||||
{{ range .Site.Sections.Reverse }}
|
||||
<a href="{{ .Permalink }}"><h4 style="display: inline-block; padding-left:.375em;padding-right:.375em;">{{ .Title }}</h4></a>
|
||||
{{ end }}
|
||||
</span>
|
||||
{{ $rss := (resources.Get "/img/rss.png").Resize "30x30" }}
|
||||
<a type="application/rss+xml" href="/blog/index.xml" target="_blank">
|
||||
<img style="padding-right: 1em" src="{{ $rss.RelPermalink }}" alt="rss icon">
|
||||
</a>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<div class="flex-wrap-container">
|
||||
<div class="container">
|
||||
<h2>Projects</h2>
|
||||
<hr>
|
||||
{{- $pageLen := len (where .Site.RegularPages "Type" "projects") -}}
|
||||
{{- range $i, $element := (where .Site.RegularPages "Type" "projects") }}
|
||||
{{ .Render "summary" }}
|
||||
{{- if lt $i (sub $pageLen 1) }} <hr> {{ end -}}
|
||||
{{- end }}
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<h2>Blog</h2>
|
||||
<hr>
|
||||
{{- $pageLen := len (where .Site.RegularPages "Type" "blog") -}}
|
||||
{{- range $i, $element := (where .Site.RegularPages "Type" "blog") }}
|
||||
{{ .Render "summary" }}
|
||||
{{- if lt $i (sub $pageLen 1) }} <hr> {{ end -}}
|
||||
{{- end }}
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<h2>Research Papers</h2>
|
||||
<hr>
|
||||
{{- $pageLen := len (where .Site.RegularPages "Type" "research papers") -}}
|
||||
{{- range $i, $element := (where .Site.RegularPages "Type" "research papers") }}
|
||||
{{ .Render "summary" }}
|
||||
{{- if lt $i (sub $pageLen 1) }} <hr> {{ end -}}
|
||||
{{- end }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
|
||||
{{ end }}
|
||||
3
themes/warwick_portfolio/layouts/partials/footer.html
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<footer>
|
||||
© Warwick New. All rights reserved. 2020 - {{now.Year}}
|
||||
</footer>
|
||||
20
themes/warwick_portfolio/layouts/partials/greeter.html
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{{ with .Site.GetPage "/greeter" }}
|
||||
{{$greeter_style := resources.Get "css/greeter.css"}}
|
||||
{{$greeter_sim := resources.Get "js/greeter.js"}}
|
||||
<link rel="stylesheet" type="" href="{{$greeter_style.RelPermalink}}">
|
||||
<div id="greeter">
|
||||
<div id="greeter-sim"></div>
|
||||
<div id="greeter-content">
|
||||
{{ .Content }}
|
||||
</div>
|
||||
<div style="text-align:center; width:100%">
|
||||
</div>
|
||||
<div>
|
||||
<a style="text-align:center" onClick="document.getElementById('homepage-header').scrollIntoView({block: 'start', behavior: 'smooth'});" >
|
||||
Scroll Down
|
||||
</a>
|
||||
<div class="scroll-down-dude" onClick="document.getElementById('homepage-header').scrollIntoView({block: 'start', behavior: 'smooth'});"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="{{$greeter_sim.RelPermalink}}"></script>
|
||||
{{ end }}
|
||||
6
themes/warwick_portfolio/layouts/partials/head.html
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<head>
|
||||
{{$styles := resources.Get "css/main.css"}}
|
||||
<link rel="stylesheet" type="" href="{{$styles.RelPermalink}}">
|
||||
{{$background := resources.Get "js/background.js"}}
|
||||
<script type="text/javascript" src="{{$background.RelPermalink}}" defer></script>
|
||||
</head>
|
||||
37
themes/warwick_portfolio/layouts/partials/header.html
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
|
||||
{{ $logo := (resources.Get "/img/logo.png").Resize "100x100" }}
|
||||
{{ $rss := (resources.Get "/img/rss.png").Resize "30x30" }}
|
||||
<header id="header" class="header">
|
||||
<div class="flex-wrap-container" style="align-items:center">
|
||||
<a href="/">
|
||||
<img style="padding-right: 1em" src="{{ $logo.RelPermalink }}" alt="logo">
|
||||
</a>
|
||||
<div>
|
||||
<a style="text-decoration: none" href="/">
|
||||
<h1 style="display:inline; color:var(--primary)">{{.Site.Title}}</h1>
|
||||
<nav aria-label="breadcrumb" >
|
||||
{{ range $index, $value := .Ancestors.Reverse }}
|
||||
{{ if (ne $index 0) }}
|
||||
<a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
|
||||
→
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
<a aria-current="page" href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
|
||||
</nav>
|
||||
</a>
|
||||
</div>
|
||||
<span style="margin-left: auto;">
|
||||
{{ range .Site.Sections.Reverse }}
|
||||
<a href="{{ .Permalink }}"><h4 style="display: inline-block; padding-left:.75em;padding-right:.75em;">{{ .Title }}</h4></a>
|
||||
{{ end }}
|
||||
</span>
|
||||
|
||||
{{ with .OutputFormats.Get "rss" -}}
|
||||
{{ printf `<link rel=%q type=%q href=%q title=%q>` .Rel .MediaType.Type .Permalink site.Title | safeHTML }}
|
||||
{{ end }}
|
||||
|
||||
<a type="application/rss+xml" href="/blog/index.xml" target="_blank">
|
||||
<img style="padding-right: 1em" src="{{ $rss.RelPermalink }}" alt="rss icon">
|
||||
</a>
|
||||
</div>
|
||||
</header>
|
||||
14
themes/warwick_portfolio/layouts/partials/taglist.html
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{{- if isset .Page.Params "tags" -}}
|
||||
{{- $tagsLen := len .Params.tags -}}
|
||||
{{- if gt $tagsLen 0 -}}
|
||||
<!-- Taglist shamelessly stolen from here: https://github.com/LukeSmithxyz/lugo/blob/master/layouts/partials/taglist.html -->
|
||||
<div style="clear:both" class=taglist>
|
||||
{{- with .Site.Params.relatedtext }}{{ . }}<br>{{ end -}}
|
||||
{{- range $k, $v := .Params.tags -}}
|
||||
{{- $url := printf "tags/%s" (. | urlize | lower) -}}
|
||||
<a id="tag_{{ . | lower }}" href="{{ $url | absURL }}">{{ . | title }}</a>
|
||||
{{- if lt $k (sub $tagsLen 1) }} · {{ end -}}
|
||||
{{- end -}}
|
||||
</div>
|
||||
{{- end -}}
|
||||
{{- end }}
|
||||
4
themes/warwick_portfolio/layouts/shortcodes/video.html
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{{ $link := .Get 0 }}
|
||||
<video width="100%" style="max-height:50vh" controls autoplay muted loop>
|
||||
<source src="{{$link}}">
|
||||
</video>
|
||||
19
themes/warwick_portfolio/theme.toml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# theme.toml template for a Hugo theme
|
||||
# See https://github.com/gohugoio/hugoThemes#themetoml for an example
|
||||
|
||||
name = "Warwick_portfolio"
|
||||
license = "MIT"
|
||||
licenselink = "https://github.com/yourname/yourtheme/blob/master/LICENSE"
|
||||
description = "A them I've created to display content in my portfolio."
|
||||
homepage = "http://example.com/"
|
||||
tags = []
|
||||
features = []
|
||||
min_version = "0.41.0"
|
||||
|
||||
[author]
|
||||
name = "Warwick New"
|
||||
homepage = "https://warwicknew.co.uk"
|
||||
|
||||
[taxonomies]
|
||||
tag = "tags"
|
||||
category = "categories"
|
||||